当前位置:编程学习 > C#/ASP.NET >>

C#解决跨线程调用错误的简单方法

在窗体程序中我们常把费时操作另开新线程,但是我们要知道新线程的运行状态,又要对UI线程进行操作来显示新线程状态;例如:
C#代码 
 
namespace CrossCall 

    public partial class Form1 : Form 
    { 
        Thread thread = null; 
        public Form1() 
        { 
            InitializeComponent(); 
            //CheckForIllegalCrossThreadCalls = false; 
            thread = new Thread(fun); 
            thread.Start();//启用新线程 
        } 
         private void fun() 
        { 
            int i = 10; 
            while (i-- > 0) 
            { 
                label1.Text = i.ToString();//在新线程中更新UI控件 
                Thread.Sleep(1000); 
            } 
        } 
        //如果程序关闭后线程还在运行,则关闭线程 
        private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
        { 
            if (thread != null) 
            { 
                thread.Abort(); 
            } 
        } 
    } 

 
 这时程序运行就发生错误了:

 这种错误我一般用以下两种方法解决:
1.对于那种明知道跨线程调用不会带来错误的,可以设置Form控件不检查跨线程调用错误,这样就不报错了。
在Form1构造方法中:
C#代码 
CheckForIllegalCrossThreadCalls = false; 
 2.但是,为了防止多个线程同时更新控件造成错误,也可以采用代理的方法:
Control .BeginInvoke 方法 (Delegate)在创建控件的基础句柄所在线程上异步执行指定委托。
这是帮助文档的例子:
 
C#代码 
public delegate void InvokeDelegate(); 
private void Invoke_Click(object sender, EventArgs e) 

   myTextBox.BeginInvoke(new InvokeDelegate(InvokeMethod)); 

public void InvokeMethod() 

   myTextBox.Text = "Executed the given delegate"; 

 如果我们不像自己去写委托,可以使用MethodInvoker 委托:
MethodInvoker 提供一个简单委托,该委托用于调用含 void 参数列表的方法。 在对控件的 Invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托。
所以,代码可改写为:
C#代码 
namespace CrossCall 

    public partial class Form1 : Form 
    { 
        Thread thread = null; 
        public Form1() 
        { 
            InitializeComponent(); 
            //CheckForIllegalCrossThreadCalls = false; 
            thread = new Thread(fun); 
            thread.Start();//启用新线程 
        } 
        private void fun() 
        { 
            int i = 10; 
            while (i-- > 0) 
            { 
                //label1.Text = i.ToString();//在新线程中更新UI控件 
                BeginInvoke(new MethodInvoker(delegate() 
                { 
                    label1.Text = i.ToString();//在新线程中更新UI控件 
                })); 
                Thread.Sleep(1000); 
            } 
        } 
        //如果程序关闭后线程还在运行,则关闭线程 
        private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
        { 
            if (thread != null) 
            { 
                thread.Abort(); 
            } 
        } 
    } 

 

程序正常执行。

补充:软件开发 , C# ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,