改善C#程序的157个建议(连载87)

发表于:2011-12-07 09:41

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:陆敏技    来源:51Testing软件测试网采编

#
DotNet
分享:

  建议87:区分WPF和WinForm的线程模型

  WPF和WinForm窗体应用程序都有一个要求,那就是UI元素(如Button、TextBox等)必须由创建它的那个线程进行更新。WinForm在这方面的限制并不是很严格,所以像下面这样的代码,在WinForm中大部分情况下还能运行(本建议后面会详细解释为什么会出现这种现象):

  • private void buttonStartAsync_Click(object sender, EventArgs e)  
  • {  
  •     Task t = new Task(() => 
  •         {  
  •             while (true)  
  •             {  
  •                 label1.Text = DateTime.Now.ToString();  
  •                 Thread.Sleep(1000);  
  •             }  
  •         });  
  •     //如果有异常,就启动一个新任务  
  •     t.ContinueWith((task) => 
  •     {  
  •         try  
  •         {  
  •             task.Wait();  
  •         }  
  •         catch (AggregateException ex)  
  •         {  
  •             foreach (Exception inner in ex.InnerExceptions)  
  •             {  
  •                 MessageBox.Show(string.Format("异常类型:{0}{1}来自:  
  •                     {2}{3}异常内容:{4}", inner.GetType(),Environment.NewLine,  
  •                     inner.Source, Environment.NewLine, inner.Message));  
  •             }  
  •         }  
  •     }, TaskContinuationOptions.OnlyOnFaulted);  
  •     t.Start();  
  • }
  •   但是,相同的一段代码如果放到WPF环境中,就肯定会抛出异常,如图所示。

    图  WPF环境中的异常

      理论上,WinForm和WPF的线程模型非常接近,它们最后都是调用API(GetMessage或PeekMessage)来处理其他线程发送过来的消息,这些消息存储在系统的一个消息队列中。在WinForm和WPF中,创建主界面的线程就是主线程,也就是UI线程,UI线程负责处理该消息队列。只是两者在处理消息队列的上层机制上稍微有一些不同,这就造成了同样的代码得到不同的结果。

      在WinForm框架中有一个ISynchronizeInvoke接口,所有的UI元素(表现为Control)都继承了该接口。其中,接口中的InvokdRequired属性表示了当前线程是否是创建它的线程。接口中的Invoke和BeginInvoke方法负责将消息发送到消息队列中,这样,UI线程就能够正确处理它了。那么,上面的这段代码在WinForm上的改进版本为(仅列出While循环部分):

  • while (true)  
  • {  
  •     if (label1.InvokeRequired)  
  •         label1.BeginInvoke(new Action(() => 
  •             {  
  •                 label1.Text = DateTime.Now.ToString();  
  •             }));  
  •     else  
  •         label1.Text = DateTime.Now.ToString();  
  •     Thread.Sleep(1000);  
  • }
  • 31/3123>
    《2023软件测试行业现状调查报告》独家发布~

    精彩评论

    关注51Testing

    联系我们

    快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

    法律顾问:上海兰迪律师事务所 项棋律师
    版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
    投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

    沪ICP备05003035号

    沪公网安备 31010102002173号