首页 > 代码库 > C# 在子线程中创建不会阻塞执行窗体

C# 在子线程中创建不会阻塞执行窗体

可以参考”C# 对 Windows 窗体控件进行线程安全调用“一文来看。

在做网络连接程序的时候碰到一个问题:每当连接到来时,都创建一个新的接收线程,而该接收线程在接收到消息时,可以创建一个新的对话窗口,而该窗口不能阻塞该接收线程的下一轮消息的接收,而且该接收线程还要把接收到的消息显示在该窗口上

Form.ShowDialog();方法弹出模态对话框,而模态对话框会阻塞后面代码的执行,导致接收线程无法继续执行(除非该模态窗口被关闭)

刚开始想到的解决办法,就是:通过Form.Show();方法,显示非模态的窗口

非模态对话框有几个问题:

(1) 生命期限问题:由于是在线程的一轮执行中创建的,所以,该对象可能在该轮结束后被垃圾回收机制自动清除掉;

(2) 模态对话框没有系统消息机制,需要自己写;(好像是这样的,没用过...)

(3) 在代码中尝试了一下,没有创建消息机制,只是显示窗口。但该窗口处于假死状态,根本没法用。

由于上述的几个困难,只能另觅它途了...

成功实验-----异步委托

在看其他文章的时候,偶然看到Control.Invoker()方法,该方法可执行自定义或系统定义的委托。

突然想起来,委托可以通过用Invoke()方法同步执行(阻塞执行),而通过BeginInvoke()方法异步执行,如果是异步执行的话,应该是不会阻塞线程的执行吧...

于是,做了如下的例子:

注意事项:

通过Invoke()/BeginInvoke()调用委托,必须由已经出现的控件来调用,否则会出现错误提示:“未经处理的异常:  System.InvalidOperationException: 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。”

 

1) 打开窗口代码:

  1. void openNewForm()  
  2. {  
  3.     Form2 newForm = new Form2();  
  4.     newForm.ShowDialog();  
  5. }
  6.  

 

(2) 线程入口函数

  1. //线程入口函数  
  2. void _threadProc()  
  3. {  
  4.     //定义一个委托实例,该实例执行打开窗口代码  
  5.     MethodInvoker mi = new MethodInvoker(openNewForm);  
  6.     BeginInvoke(mi);  
  7.   
  8.     //如果没有阻塞的话,该段代码应该可执行  
  9.     Console.WriteLine("新打开的窗口没有阻塞之后的执行");  
  10.     Console.ReadLine();  
  11. }  

 

(3) 创建,并执行线程

  1. Thread newThread = new Thread(new ThreadStart(_threadProc));  
  2. newThread.Start(); 

4) 设置项目的输出类型为:控制台应用程序(这样执行的时候会同时弹出控制台和窗口)

执行结果如下:

可见,新打开的模式窗口并没有阻塞线程的执行!

因为,如果是同步调用的话,在Form2窗口关闭之前,“新打开的窗口没有阻塞之后的执行”就不会有输出。

技术分享

技术分享

 

技术分享

 

本文非自创,可查看原文:http://blog.csdn.net/xiaobai1593/article/details/7290421

 

C# 在子线程中创建不会阻塞执行窗体