c# 多线程的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c# 多线程的问题相关的知识,希望对你有一定的参考价值。

private Thread td;
public Form1()

InitializeComponent();


private void button1_Click(object sender, EventArgs e)

label4.Text = "";
label4.Update();
button1.Enabled = false ;
button2.Enabled = false ;
groupBox1.Text = "程序正在运行……";
//groupBox1.Update();
groupBox1.Refresh();
td = new Thread(new ThreadStart(progprocess));
td.Start();
this.button1.Enabled = true;
this.button2.Enabled = true;
groupBox1.Text = "程序运行结束!";



private void button2_Click(object sender, EventArgs e)

this.Close();

private void progprocess()

for (int i = 1; i <= 100; i++)

for (int j = 1; j <= 100000; j++)

if (j % 100 == 0) this.progressBar2.Value = j;

this.progressBar1.Value = i;
label4.Text = i.ToString() + "%";
//label4.Update();
label4.Refresh();





我点击按扭的时候出现:线程间操作无效: 从不是创建控件“label4”的线程访问它的错误。
我知道是跨线程使用windows窗体控件的问题,但是我听说跨线程使用windows窗体控件是不安全线程访问,有可能引起程序意想不到的问题,但是像上面说的错误,又必须跨线程使用windows窗体控件,这样是不是矛盾了,有没有不用跨线程使用窗体控件,或是跨线程使用窗体控件是可控的,也可以是安全的。

在.NET中,为了线程调用安全,其他线程是不能访问UI线程中的控件的
需要写一个委托,回挂到UI线程中去

//要使用Invoke必须要传递一个委托 所以 先定义一个委托
private delegate void UIInvokeHandler (int i);
private void button1_Click(object sender, EventArgs e) //按钮单击事件

int num;
if(Int32.TryParase(TextBox.text,out num))

output(num); 这里跨线程调用控件


//任何时候要调用窗体控件时调用这个函数,而不是下面那个protected void atry(int n)
//这个函数可以根据你的调用是否跨线程的而进行相应的处理
protected void output(int n) 这个函数是关键

if(this.IvokeRequired) //根据这个标志判断是否需要跨线程
//是跨线程调用则用Invoke的方式,在创建的线程内执行
UIInvokeHandler deloutput = new UIInvokeHandler (atry);
//在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托
this.Invoke(deloutput,n); //如果有多个参数,则用一个object数组

else

//如果不是跨线程调用,则直接访问
atry(n);


//真正的事件处理方法,委托的实际执行函数
protected void atry(object m)
int n = (int)m;
richTextBox1.Clear();
for(int i = 1; i<= n; ++i)
richTextBox1.Clear();.AppendText(i.ToString);


几点说明:
public bool InvokeRequired get;
System.Windows.Forms.Control 的成员
获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中
如果控件的 System.Windows.Forms.Control.Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke 方法对控件进行调用),则为 true;否则为 false。
参考技术A 不是在调试模式下使用时,是不会提示错误的,但是这不是线程安全的,你当然可以用锁的方式来保证安全,但是不推荐。
推荐用delegate来ui代理调用,这样是安全的。
______________________________
具体就是
声明原型
delegate void Worker();
void Work();
定义
Worker worker=new Worker(form1.Work);
使用
worker.Invoke(params);
____________________________本回答被提问者采纳
参考技术B td = new Thread(new ThreadStart(progprocess));
td.Start();
这个线程不是UI线程自然不能更改UI的东西了。
你的Invoke一下UI线程来操作。
参考技术C 最近很多人问多线程的问题,
http://zhidao.baidu.com/question/79980016.html
http://zhidao.baidu.com/question/80234484.html
中有我为这类相关问题写的例子.敬请参考.

c#多线程

    this.Close();   只是关闭当前窗口,若不是主窗体的话,是无法退出程序的,另外若有托管线程(非主线程),也无法干净地退出;
    Application.Exit();  强制所有消息中止,退出所有的窗体,但是若有托管线程(非主线程),也无法干净地退出;
    Application.ExitThread(); 强制中止调用线程上的所有消息,同样面临其它线程无法正确退出的问题;
    System.Environment.Exit(0);   这是最彻底的退出方式,不管什么线程都被强制退出,把程序结束的很干净。

 

以上是关于c# 多线程的问题的主要内容,如果未能解决你的问题,请参考以下文章

C#多线程之旅

C#多线程之旅——介绍和基本概念

C#多线程之旅

C#多线程如何处理数据

C# 关于多线程和CPU的问题

C#多线程解决程序卡顿问题