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

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

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

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

  BeginInvoke方法接受的是一个Delegate类型的参数,在这里我们用一个Action来实现。

  WPF应用程序的线程模型则完全依赖于DispatcherObject类型。所有的WPF控件都继承自一个抽象类Visual,而这个抽象类又最终继承自DispatcherObject类型。在这个DispatcherObject类型中有一个属性,两个方法。属性Dispatcher完成所有的工作线程和UI线程之间的调度任务。CheckAccess方法负责检测工作线程是否可以访问控件,如果是,则返回True;否则返回False。VerifyAccess方法则负责检测工作线程是否具有控件的访问权限,如果不能访问则抛出异常InvalidOperationException。

  WinForm应用程序用类似CheckAccess的方式进行访问权限的判断;WPF应用程序则进行了改进,所有的UI控件都采用VerifyAccess的方式进行工作线程访问权限的判断。这直接决定了本建议开头处那个例子的输出,WPF只要判断出工作线程和UI线程不是同一个线程的,则直接抛出异常,而WinForm却有成功执行的余地。但是,WinForm的这种机制直接造成了程序的不稳定,因为即使在大部分情况下代码能很好的工作,可是在不确定的情况下,那样的代码中工作线程会直接操作UI元素,这样还是会抛出异常的。

  考虑到WinForm在这个问题上的局限性,再次对WinForm的线程模型处理进行改进:

  • //用于表示主线程,在本例中就是UI线程  
  • Thread mainThread;  
  • bool CheckAccess()  
  • {  
  •     return mainThread == Thread.CurrentThread;  
  • }  
  • void VerifyAccess()  
  • {  
  •     if (!CheckAccess())  
  •         throw new InvalidOperationException("调用线程无法访问此对象,  
  •             因为另一个线程拥有此对象");  
  • }  
  • private void buttonStartAsync_Click(object sender, EventArgs e)  
  • {  
  •     //当前线程就是主线程  
  •     mainThread = Thread.CurrentThread;  
  •     Task t = new Task(() => 
  •         {  
  •             while (true)  
  •             {  
  •                 if (!CheckAccess())  
  •                     label1.BeginInvoke(new Action(() => 
  •                         {  
  •                             label1.Text = DateTime.Now.ToString();  
  •                         }));  
  •                 else  
  •                     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();  
  • }
  • 32/3<123>
    《2023软件测试行业现状调查报告》独家发布~

    精彩评论

    关注51Testing

    联系我们

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

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

    沪ICP备05003035号

    沪公网安备 31010102002173号