C# 中跨线程访问控件

一、简述

C#中不允许跨线程直接访问界面控件,即一个线程中如主线程创建的控件不允许被其他线程例如子线程直接访问,如果直接访问或设置属性则会爆出"调用线程无法访问此对象,因为另一个线程拥有该对象"等类似错误。

在一个线程中设置其他线程所有的控件属性通常有两种方法,一是设置System.Windows.Forms.Control的CheckForIllegalCrossThreadCalls属性值为false,表示不对错误线程的调用进行捕捉,这种方法只对winforms界面框架有效,在WPF中无法设置该属性,只能使用第二种方法。

第二种方法是通过委托来实现控件属性设置,需要通过InvokeBeginInvoke来实现,Invoke表示同步,BeginInvoke表示异步,下面列举了在winforms中和WPF两种界面框架中跨线程访问控件的代码示例。

二、Winforms中跨线程访问控件

一般的委托方法示例代码如下:

csharp 复制代码
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;
}

也可以采用匿名代理的方式,示例代码如下:

csharp 复制代码
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的代码。示例代码如下:

csharp 复制代码
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),以避免此处异常中断。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:CastleWu

出处:cnblogs.com/castlewu/p/17168964.html

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

相关推荐
MZWeiei33 分钟前
Scala:case class(通俗易懂版)
开发语言·后端·scala
飞向星河1 小时前
SV学习笔记——数组、队列
笔记·学习·c#
小杨4041 小时前
springboot框架项目实践应用三(监控运维组件admin)
spring boot·后端·监控
sevevty-seven2 小时前
Spring Boot 自动装配原理详解
java·spring boot·后端
lamdaxu3 小时前
分布式调用(02)
后端
daiyunchao3 小时前
让Pomelo支持HTTP协议
后端
芒猿君3 小时前
AQS——同步器框架之源
后端
SaebaRyo4 小时前
手把手教你在网站中启用https和http2
后端·nginx·https
緣木求魚4 小时前
c#结合IL(中间语言)分析Try-Catch的内部机制及其对性能的影响
c#·il