c#,Winform多线程的问题。大家帮我想想办法把!

yaoohfox 2009-03-24 12:18:49
1.在Winform中要做一个多线程的东西。
有两个数组。int a[1000],int b[1000]
2.点击开始按钮后,分别启动两个线程去遍历数组a 和数组b.在遍历的同时,将遍历信息输出到TextBox或者其他的可以显示遍历信息的控件。或者用progerssbar显示遍历的进度。这两个线程不涉及到通讯。
3.点击取消按钮,如果a,b数组没有遍历完的话,就停止遍历。

不知道这个功能怎么做。要是哪位大虾能给个Demo就好了。或者给个提示。我自己做多线程的时候,比如点击开始按钮后,执行如下功能:
Thread t1 = new Thread(new ThreadStart(Func1));//
Thread t2 = new Thread(new ThreadStart(Func2));//
t1.Start();
t2.Start();
t1.Join();
t2.Join();

private void Func1()
{
for (int i = 0; i < 1000; i++)
{
TextBox.Text=i.ToString();
好像多线程调用控件时,会出问题。
Thread.Sleep(500);
}
}

各位帮我想想办法把。不知道怎么办的帮我顶顶吧。没天发一贴,系统给你加人情分哦!
...全文
563 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
zujinsheng 2011-09-26
  • 打赏
  • 举报
回复
MARK 学习
Bodil 2009-05-04
  • 打赏
  • 举报
回复
好帖。。。mark下来
marvelstack 2009-03-27
  • 打赏
  • 举报
回复
楼主这个问题也比较经典,可以通过BackgroundWorker组件来比较好的解决,同时支持UI线程和非UI线程之间的交互,处理中可以停止执行过程。

下面的两篇文章比较详细的介绍了该功能,并提供实例代码,建议楼主参考一下。


使用BackgroundWorker组件进行异步操作编程
http://blog.csdn.net/zhzuo/archive/2008/07/23/2699305.aspx

实现增强的异步任务执行组件
http://blog.csdn.net/zhzuo/archive/2008/07/23/2699847.aspx
yaoohfox 2009-03-26
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 birdlonger 的回复:]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Collections;

namespace 多线程_读取数组显示TextBox_03._5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeCompone…
[/Quote]
感谢birdlonger 的回复,你的方法我试过了,确实 很好。谢谢啦。如果在F1里不加Thread.Sleep(500); 这句的话,UI好像还是会死掉。其实我想在程序处理过程中,实时显示处理信息。类似杀毒软件,一个线程在杀毒,在UI显示扫描文件夹信息。同时如果有病毒的话,还能提示病毒信息。不知道你有好的方法不?等你的回复。
birdlonger 2009-03-25
  • 打赏
  • 举报
回复
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Collections;

namespace 多线程_读取数组显示TextBox_03._5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
st = new setText(this.SetTextBox1);
}
int[] s1 = new int[5] { 1, 2, 3, 4, 5 };
string[] s2 = new string[5] { "000", "001", "002", "003", "004" };
Thread t1;
Thread t2;
public delegate void setText (string str );
public void SetTextBox1(string str)
{

if (this.InvokeRequired)
{

this.Invoke(this.st, str);

}
else
{
this.textBox1.Text += str;
}

}
setText st ;

public static object o= new object();
public void F1()
{

for (int i = 0; i < s1.Length; i++)
{
string str = s1[i].ToString() + "\r\n";
st(str);
Thread.Sleep(500);
}

}
public void F2()
{
for (int i = 0; i < s2.Length; i++)
{
string str = s2[i].ToString() + "\r\n";
st(str);
Thread.Sleep(500);
}

}
private void button1_Click(object sender, EventArgs e)
{
t1 = new Thread(new ThreadStart(F1));
t2 = new Thread(new ThreadStart(F2));
t1.Start();
t2.Start();
}

private void button2_Click(object sender, EventArgs e)
{
t1.Join();
t2.Join();
}
}

}
yaoohfox 2009-03-25
  • 打赏
  • 举报
回复
各位我用backgroupwork算是基本完成我要的功能了,本来我是打算用两个线程分别去做a数组和b数组的遍历,同时在遍历的时候,在TextBox里显示遍历的实时信息。但是没搞出来。就用backGroupWork里把两个数组都做遍历,同时显示a和 b的遍历信息。只能算是交个差,但是没能完成我想要的功能。
不知道你们有什么更好方法没?我随时关注。贴我肯定会结的。能提出好的方法的,分数肯定是有的,就当是讨论。大家一起出处主意。好的方法最好把例子程序贴出来。这样我也好在机器上跑跑,实验下方法。
辛苦各位了。
cc_net 2009-03-24
  • 打赏
  • 举报
回复
不能在非UI线程中操作控件,编译会有错误,吧你方法改下。

private delegate void Client();//定义代理

private void Func1()
{
if (this.textBox.InvokeRequired)//等待异步
{
Client cl = new Client(Func1);
this.Invoke(cl);//通过代理调用刷新方法
}
else
{
for (int i = 0; i < 1000; i++)
{
TextBox.Text=i.ToString();
Thread.Sleep(500);
}
}
}
heyu52 2009-03-24
  • 打赏
  • 举报
回复
你用两个backgroupwork控件就完事了,里面的事件刚好达到你要的要求
private void bgwCopyAssembly_DoWork(object sender, DoWorkEventArgs e)
{
DoWork();
}

private void bgwCopyAssembly_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.PerformStep();
}

private void bgwCopyAssembly_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar.Value = progressBar.Maximum;
Close();
}
zjh222 2009-03-24
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 cc_net 的回复:]
C# codeprivatevoidbutton1_Click(objectsender, EventArgs e)
{
Thread t=newThread(newThreadStart(Func1));
t.Start();
}privatedelegatevoidChange(inti);privatevoidtest(inti)
{if(this.InvokeRequired)
{this.BeginInvoke(newChange(test), i);
}else{
textBox1.Text=i.ToString();
}
}privatevoidFunc1()…
[/Quote]

我想中途退出,点了X和用this.dispose()都不管用呢??如何杀死这个线程呢??
cc_net 2009-03-24
  • 打赏
  • 举报
回复
之前写的UI会死掉是因为,执行了this.Invoke整个Fun1方法被封送到了UI线程,在UI线程中执行整个Fun1方法,实际是同步的,所以之前用的多线程失去了意义。

修改后,吧textBox1.Text = i.ToString();独立出来,这个时候Func1()不在UI中执行,在另一个线程工作,每次只有textBox1.Text = i.ToString();被送到UI界面执行。所以界面就不会假使了。
cc_net 2009-03-24
  • 打赏
  • 举报
回复

private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(Func1));
t.Start();
}


private delegate void Change(int i);

private void test(int i)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new Change(test), i);
}
else
{
textBox1.Text = i.ToString();
}
}


private void Func1()
{
for (int i = 0; i < 1000; i++)
{
test(i);
Thread.Sleep(500);
}
}
脱离语言 2009-03-24
  • 打赏
  • 举报
回复
for (int i = 0; i < 1000; i++)
{
TextBox.Text=i.ToString();
好像多线程调用控件时,会出问题。
Thread.Sleep(500);
}

执行完这段代码后才能返回,返回后才能看到运行结果,所以当然不对了呀。
Thread.Sleep(500)是程序停止执行,等500毫秒呀。
用线程,Invoke,委托。
yaoohfox 2009-03-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 swalp 的回复:]
留个位置,搬凳子来学习
[/Quote]
通过使用代理,然后调用Invoke方法我试过,有个问题比如我有10000个数据在做的话,UI就死掉了。而且更新UI的时候只能看到最后的结果值。
另外backgroupwork控件我觉得也是可以做到,但是要用到两个,显示给UI的提示信息不太好。我在试试。各位如果有更好的方法,贴出来一起学习下。
搞不出来了,现在先尝试用backgroupwork控件做做。如何用多线程的东西,比较麻烦,我比较偏向使用多线程去完成这个功能。
各位如果写代码的话,尽量详细点,最好是个 DEMO。
谢谢了。看到大家这么热心。泪奔。。。。。。
cxzy0930 2009-03-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 cc_net 的回复:]
不能在非UI线程中操作控件,编译会有错误,吧你方法改下。

C# code
private delegate void Client();//定义代理

private void Func1()
{
if (this.textBox.InvokeRequired)//等待异步
{
Client cl = new Client(Func1);
this.Invoke(cl);//通过代理调用刷新方法
}
else
{
for (int i = …
[/Quote]

正确的
swalp 2009-03-24
  • 打赏
  • 举报
回复
留个位置,搬凳子来学习
cppfaq 2009-03-24
  • 打赏
  • 举报
回复
看看这个:
http://blog.sina.com.cn/s/blog_4cb80898010009de.html
cppfaq 2009-03-24
  • 打赏
  • 举报
回复
关闭CheckForIllegalCrossThreadCalls,这是Control class上的一个static property,默认值为flase,目的在于开关是否对Handle的可能存在的不一致存取的监测;且该项设置是具有Application scope的。

如果,只需要在某些Form中消除Cross-thread InvalidOperationException建议,可以在Form的.ctor中,InitializeComponent语句后将CheckForIllegalCrossThreadCalls设置为false 。
public Form1() {
InitializeComponent();

Control.CheckForIllegalCrossThreadCalls = false;
}
beargo 2009-03-24
  • 打赏
  • 举报
回复
this.Invoke(cl);//通过代理调用刷新方法
jwdream2008 2009-03-24
  • 打赏
  • 举报
回复
方法1:
可以在构造函数里设置..

this.CheckForIllegalCrossThreadCalls =false;
方法2:
通过委托:
创建代理delegate void SetTextCallback(string text);
创建和启动线程this.demoThread = new Thread(new ThreadStart(this.ThreadProcUnsafe));
this.demoThread.Start();
线程中要求改主窗体UI中的text属性private void ThreadProcSafe()
{
this.SetText("This text was set safely.");
}
调用窗体中的函数用invoke传递参数private void SetText(string text) { if (this.textBox1.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.textBox1.Text = text; } }
jwdream2008 2009-03-24
  • 打赏
  • 举报
回复
方法1:
创建代理delegate void SetTextCallback(string text);
创建和启动线程this.demoThread = new Thread(new ThreadStart(this.ThreadProcUnsafe));
this.demoThread.Start();
线程中要求改主窗体UI中的text属性private void ThreadProcSafe()
{
this.SetText("This text was set safely.");
}
调用窗体中的函数用invoke传递参数private void SetText(string text) { if (this.textBox1.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.textBox1.Text = text; } }
加载更多回复(1)

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧