处理WinForm多线程程序时的陷阱

原创 2005年05月28日 15:48:00

与所有的UI开发平台一样,.NET下线程开发图形界面同样要遵循一个基本原则:就是对UI对象的操作一定要在产生该UI对象的线程里进行(该线程称作UI线程),因为大部分UI对象都不是线程安全的。

.NET中,把调用调用放在UI线程里执行是通过Form类及其子类的Invoke()方法实现的(具体的过程请参考其他资料),可以这样做是因为Form对象保存了创建它的线程的信息,而且Form类有一个bool类型的属性InvokeRequired,可以通过它查看当前线程是否为创建该Form对象的线程(UI线程)——如果为true,则表示当前线程不是UI线程,反之则是。下面提供一个例子:

using System.Threading;

using System.Windows.Forms;

 

namespace csharpTest

{

     public class TestForm : Form

     {

         private Form form1;

         private Form form2;

 

         public static void Main()

         {

              TestForm tf = new TestForm();

              tf.Show();

              tf.UIThread();

              Application.Run();

         }

 

         public void UIThread()

         {

              form1 = new Form();

              form2 = new Form();

              form2.Show();//这里是关键

              form1.Show();

              Thread thread = new Thread(new ThreadStart(WorkerThread));

              thread.Start();

         }

 

         public void WorkerThread()

         {

              if (form2.InvokeRequired)

                   form2.Invoke(new MethodInvoker(WorkerThread));

              else

              {

                   form1.Text = "This is from WorkerThread.";

              }

         }

 

         protected override void OnClosing(System.ComponentModel.CancelEventArgs e)

         {

              base.OnClosing (e);

              Application.Exit();

         }

     }

}

TestForm里有两个需要注意的方法,UIThread——用来模拟UI线程,WorkerThread——用来模拟用户线程,UIThread中实例化了成员form1form2并调用了它们的Show方法,在WorkerThread中改变form1Text属性。请注意WorkerThread里有个技巧, if (form2.InvokeRequired) 即如果当前线程不是创建该form2的线程,则将方法通通过过Invoke方法放到UI线程里去执行。但就是这里问题出现了form1form2都是在UIThread里建立的,所以它们保存的线程的信息应该是一样的。所以form1.InvokeRquiredform2.InvokeRquired的值在任何线程里都是一样的,即在WorkerThreadInvokeRquire的值都应该是true(因为在不同的线程里)。但是如果注释掉form2.Show()的话form2.InvokeRquiredWorkerThread中的值却是false(在vs.net中调试看到),怎么会这样呢?而且如果不经过判断直接在WorkerThread里调用form2对象的Invoke的话…………居然会抛出异常——“在创建窗口句柄之前,不能在控件上调用 Invoke InvokeAsync

分析一下该异常的信息,在win32里每一个窗体都有一个窗体句柄,是该窗体在建立时系统分配的,但我们确实在UI线程里建立了form2对象的。这里有个误区.Net里的Form对象并不是和win32的窗体对象完全对应的。本人窃以为,产生一个Form类的实例时,只是产生了一个内存中的普通的对象,并不产生系统窗体(好像叫做User对象吧),只有它第一次呈现在屏幕上(或称作创建)时,才产生系统里表示窗体的User对象且分配句柄,对应的WIN32 APICreateWindow()方法大概也在这个时候执行(先声明:本人对WIN32 AP 并不熟悉,所以这里如果有什么不妥的话请大家指正)

只有.NET里的form对象调用某种方法使系统产生真正的窗体时,form才会有创建它的线程的信息,且InvokeRquired才有效,即才能调用formInvoke方法。不过我还没弄清楚哪几个方法可以做到。据我所知Show, CreateGraphics可以产生系统真正的系统窗体。

处理WinForm多线程程序时的陷阱

  与所有的UI开发平台一样,.NET下线程开发图形界面同样要遵循一个基本原则:就是对UI对象的操作一定要在产生该UI对象的线程里进行(该线程称作UI线程),因为大部分UI对象都不是线程安全的。   ...
  • xiaojian
  • xiaojian
  • 2007年06月06日 21:43
  • 470

处理WinForm多线程程序时的陷阱,出现窗口句柄为创建就被访问

  与所有的UI开发平台一样,.NET下线程开发图形界面同样要遵循一个基本原则:就是对UI对象的操作一定要在产生该UI对象的线程里进行(该线程称作UI线程),因为大部分UI对象都不是线程安全的。  在...
  • beelinkerlidejun
  • beelinkerlidejun
  • 2009年11月05日 16:49
  • 2874

一起来谈谈,面试中的那些“陷阱问题”

1. 前言众所周知,我们在面试的时候,HR 会通过各种各样的问题来“刁难”你。但是面对这些问题,每个人的反应会各不相同,HR 也就能以此来推断出你平时大概是个什么样子的人,并考虑你是否合适这个职位。可...
  • MR_LP
  • MR_LP
  • 2016年12月21日 11:46
  • 2856

操作系统—陷阱、中断、异常

在操作系统中,陷阱,中断和异常是常见的术语,它们贯穿操作系统学习的始终,这篇文章主要区分它们之间的不同。 陷阱 计算机有两种运行模式:用户态, 内核态。 其中操作系统运行在内核态,在内核态中,操作...
  • qq_30866297
  • qq_30866297
  • 2016年07月27日 16:20
  • 642

中断和陷阱的区别(转载)

外部中断,就是我们通常所说的中断(interrupt)。对于执行的系统来说,这种中断发生完全是"异步"的,根本无法预测到此类中断会在什么时候发生。因此,CPU(或者软件)对于此类外部中断完全是"被动"...
  • fantasyagain
  • fantasyagain
  • 2011年01月06日 09:59
  • 4666

Java中的陷阱

Java中创建对象的常规方式有如下5种:           1. 通过new调用构造器创建Java对象;         2. 通过Class对象的newInstance()方法调用构造器创建对象;...
  • geloin
  • geloin
  • 2013年11月06日 14:05
  • 2292

子序列的和(注意溢出问题)

输入两个正整数n 分析:还是for循环累加。 本题陷阱在于n比较大时,n*n会溢出,所以 1/n^2 应该用 1/n/n 而不是 1/(n*n)。...
  • leafinsnowfield
  • leafinsnowfield
  • 2014年10月08日 22:00
  • 405

多线程程序常见Bug剖析(上)

多线程程序常见Bug剖析(上) 编写多线程程序的第一准则是先保证正确性,再考虑优化性能。本文重点分析多线程编程中除死锁之外的另两种常见Bug:违反原子性(Atomicity Violat...
  • jfkidear
  • jfkidear
  • 2014年04月11日 14:54
  • 1081

扇形陷阱和断层陷阱(即当一个实体有多个一对多关系时)

设计关联是数据库设计中必经的一个环节。在实体建立之后,我们开始考虑实体与实体之间的相互关系,从而建立关联。然而在实际操作中,关联的设计常常会进入误区。下面介绍两种比较著名的扇形陷阱(FanTraps)...
  • gao8658
  • gao8658
  • 2011年08月26日 21:10
  • 1897

SNMP陷阱(SNMP Trap)

SNMP陷阱(SNMP Trap)是由一个SNMP代理发送的信息给管理员,其使一个代理通知管理站的重要事件,通过一个未被请求的SNMP信息。在SNMP自陷的通知后面的观点是这样的:如果一个管理员是负责...
  • gxj022
  • gxj022
  • 2009年09月11日 08:51
  • 1874
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:处理WinForm多线程程序时的陷阱
举报原因:
原因补充:

(最多只允许输入30个字)