C#中跨线程访问控件的实现方法
作者:小码编匠
一、简述
C#中不允许跨线程直接访问界面控件,即一个线程中如主线程创建的控件不允许被其他线程例如子线程直接访问,如果直接访问或设置属性则会爆出“调用线程无法访问此对象,因为另一个线程拥有该对象”等类似错误。
在一个线程中设置其他线程所有的控件属性通常有两种方法,一是设置System.Windows.Forms.Control的CheckForIllegalCrossThreadCalls属性值为false,表示不对错误线程的调用进行捕捉,这种方法只对winforms界面框架有效,在WPF中无法设置该属性,只能使用第二种方法。
第二种方法是通过委托来实现控件属性设置,需要通过Invoke或BeginInvoke来实现,Invoke表示同步,BeginInvoke表示异步,下面列举了在winforms中和WPF两种界面框架中跨线程访问控件的代码示例。
二、Winforms中跨线程访问控件
一般的委托方法示例代码如下:
delegate void delegateSetText(string str);//定义一个委托 private void SetText(string str) { if (InvokeRequired)//判断是否是被其他线程调用 { delegateSetText delegatesetText01 = new delegateSetText(SetText); Invoke(delegatesetText01, new object [] {str}); return; } textBox01.Text = str; }
也可以采用匿名代理的方式,示例代码如下:
delegate void delegateSetText(string str);//定义一个委托 private void SetText(string str) { delegateSetText delegatesetText01 = delegate(string str01) { textBox01.Text = str01; } Invoke(delegatesetText01, new object [] {str}); }
三、WPF中跨线程访问控件
在WPF中跨线程访问控件需要使用Dispatcher。Dispatcher是WPF中的线程调度管理器,用在子线程刷新主线程(UI线程)(比如绑定的时候,属性更新的时候),在子线程里面起一个dispatcher,将工作项目调度到 UI 线程,让主线程调度刷新UI的代码。示例代码如下:
private void SetText(string str) { if (!Dispatcher.CheckAccess())//判断是否是被其他线程调用 { Dispatcher.Invoke(() => SetText(str)); return; } textBox01.Text = str; }
【注】
避免”在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。“错误。
一个Form窗体必须完全创建完成,才能调用它自身或它上面控件的Invoke或BeginInvoke。
经测试,窗体的构造函数内的InitializeComponent()的执行完成时,窗体并未创建完成;窗体的构造函数执行完成时,窗体也并未创建完成;
在form.show()后,窗体是已经创建完成了。
另外,可以在调用Invoke()前,判断一下 if (form.Created),以避免此处异常中断。
最后
到此这篇关于C#中跨线程访问控件的方法的文章就介绍到这了,更多相关C#跨线程访问控件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!