当前位置: 移动技术网 > IT编程>开发语言>.net > winform 跨线程访问问题

winform 跨线程访问问题

2019年02月23日  | 移动技术网IT编程  | 我要评论

郭海藻原型,慧耕思网易博客,星辰飞飞官网

一、问题描述

进行winform 开发我们在进行数据交换时避免不了使用多线程或异步方法,这样操作也将避免不了跨线程对控件进行操作(赋值、修改属性)。

下面通过一个测试说明一下问题

点击一个按钮异步对textbox进行赋值

运行测试结果

1 private void button1_click(object sender, eventargs e)
2 {        
3               action<string> action = new action<string>((str) =>
4               {
5                   // 解决跨线程赋值
6                   this.textbox1.text = str;              
7               });
8               action.begininvoke("test", null, null);      
9 }
view code

产生错误的原因:textbox1是由主线程创建的,异步方法(或子线程)是另外创建的一个线程,在.net上执行的是托管代码,c#强制要求这些代码必须是线程安全的,即不允许跨线程访问windows窗体的控件。

二、解决方法

1.在窗体的加载事件中,将c#内置控件(control)类的checkforillegalcrossthreadcalls属性设置为false,屏蔽掉c#编译器对跨线程调用的检查。

1 //取消跨线程的访问
2 control.checkforillegalcrossthreadcalls = false;
view code

使用上述的方法虽然可以保证程序正常运行并实现应用的功能,但是在实际的软件开发中,做如此设置是不安全的(不符合.net的安全规范),在产品软件的开发中,此类情况是不允许的。如果要在遵守.net安全标准的前提下,实现从一个线程成功地访问另一个线程创建的空间,要使用c#的方法回调机制。

2.使用回调函数 ( 委托的应用 )

(1) 定义声明回调

(2) 初始化回调

(3) 触发动作

 1         /// <summary>
 2         /// 定义委托
 3         /// </summary>
 4         /// <param name="str"></param>
 5         private delegate void setvaluedelegate(string str);
 6 
 7         /// <summary>
 8         /// 声明委托
 9         /// </summary>
10         setvaluedelegate test;
11 
12         /// <summary>
13         /// 回调方法
14         /// </summary>
15         /// <param name="str"></param>
16         private void settbvalue(string str)
17         {
18             this.textbox1.text = str;
19         }
20 
21         private void button1_click(object sender, eventargs e)
22         {
23             // 实例化委托    
24             test = new setvaluedelegate(settbvalue);
25 
26             action<string> action = new action<string>((str) =>
27             {
28                   // 解决跨线程赋值                 
29                   this.textbox1.invoke(test, str);
30              });
31 
32             action.begininvoke("test", null, null);
33         }
view code

我个人比较使用喜欢使用事件解决(原理同委托一样),但省掉不少代码

 1         private void button1_click(object sender, eventargs e)
 2         {
 3             action<string> action = new action<string>((str) =>
 4               {
 5                   // 解决跨线程赋值            
 6                   this.textbox1.invoke(
 7                       new action<string>((param) =>
 8                       {
 9                           this.textbox1.text = param;
10                       }
11                       ), str);
12               });
13 
14             action.begininvoke("test", null, null);
15         }
view code

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网