在非UI 线程上Show一个含有WebBrowser的Form出现的问题

问题描述: 客户端的Windows程序使用WebMethod从服务器上取得一个系统信息列表。信息列表中有多条Message。当系统消息的时间合要求,使用一个自定义的MessageForm Show出这个系统Message。MessageForm是一个含有WebBrowser的WinForm。 Show MessageForm的调用在一个Timer中被执行。当调用ShowMessage的操作时会出现下面的错误。 出错的代码:

private void btnTestS_Click(object sender, EventArgs e)         {             DataRow row = (new DataTable()).NewRow();             System.Threading.Timer timer = new System.Threading.Timer(                 new System.Threading.TimerCallback(ShowMessageFormS),                 row,                 0,                 30000);         }         private void ShowMessageFormS(object status)         {             (new MessageForm()).Show();         }

在new MessageForm时,MessageForm调用自己的InitializeComponent()方法时出错。如果把MessageForm上的WebBrowser控件删除掉,程序可以正常Show出Form,不出错。
问题调查: 从程序的错误信息看出,可能是ActiveX的套间问题。ActiveX的WebBrowser要求当前Thread是一个single-thread apartment。WebBrowser Com组件要求当前线程是一个单套间的,而System.Threading.Timer起来的线程是一个MTAThread 多套间的。产生了问题。
修改方案: 修改方案一: 使用一个新线程启动MessageForm,设置这个线程的ApartmentState为STA

private void btnTestT_Click(object sender, EventArgs e)         {             DataRow row = (new DataTable()).NewRow();             System.Threading.Timer timer = new System.Threading.Timer(                 new System.Threading.TimerCallback(ShowMessageFormT),                 row,                 0,                 300000);         }
        private void ShowMessageFormT(object status)         {             System.Threading.Thread thread = new System.Threading.Thread(                 new System.Threading.ParameterizedThreadStart(ShowMessage));             thread.SetApartmentState(System.Threading.ApartmentState.STA);             thread.Start(status);         }
        private void ShowMessage(object status)         {             System.Windows.Forms.Application.Run(new MessageForm());             (new MessageForm()).ShowDialog();         }

修改方案二:找到主UI线程,用主UI线程调度,Show MessageForm

private void btnTestG_Click(object sender, EventArgs e)         {             DataRow row = (new DataTable()).NewRow();             System.Threading.Timer timer = new System.Threading.Timer(                 new System.Threading.TimerCallback(ShowMessageFormG),                 row,                 0,                 300000);         }         private delegate void ShowMessageHandler(DataRow row);         private void ShowMessageFormG(object status)         {             if (System.Windows.Forms.Application.OpenForms[0].InvokeRequired)             {                 System.Windows.Forms.Application.OpenForms[0].Invoke(new ShowMessageHandler(ShowMessageFormG), new object[] { status });                 return;             }             ShowMessage(status);         } private void ShowMessage(object status)         {             (new MessageForm()).ShowDialog();         }

示例中的DataRow row = (new DataTable()).NewRow(); 没有实际意义,在实际代码中ShowMessage需要一个DataRow来绘制消息。示例代码中的DataRow只是为了模拟实际的环境,没有实际意义。

参考:http://www.zhangsichu.com/blogview.asp?content_id=79

时间: 2024-10-09 07:03:57

在非UI 线程上Show一个含有WebBrowser的Form出现的问题的相关文章

Android自定义组件系列【12】——非UI线程绘图SurfaceView

一.SurfaceView的介绍 在前面我们已经会自定义View,使用canvas绘图,但是View的绘图机制存在一些缺陷. 1.View缺乏双缓冲机制. 2.程序必须重绘整个View上显示的图片,比较耗资源. 3.非UI线程无法更新View组件,所以会占用主线程资源,当需要在主线程中处理逻辑的时候会很慢. 在Android中为我们提供了一个SurfaceView来替代View实现绘制图形,一般在游戏绘图方面应用较广,所以如果是比较复杂的绘图建议使用SurfaceView. 二.SurfaceV

SWT的UI线程和非UI线程

要理解UI线程,先要了解一下"消息循环"这个概念.链接是百度百科上的条目,简单地说,操作系统把用户界面上的每个操作都转化成为对应的消息,加入消息队列.然后把消息转发给对应的应用程序(一般来说,就是活动窗口),应用程序根据自己的逻辑处理这些消息. 如果应用程序处理某个消息事件的时候,用了很长的时间,这时候后续的消息无法及时得到处理,就会造成应用程序没有响应,也就是常说的"假死"状态. 所以,应用程序如果处理某个事件需要较长的时间,需要把这个操作放到一个另外的线程中进行

关于 SWT 的UI线程和非UI线程

要理解UI线程,先要了解一下"消息循环"这个概念.链接是百度百科上的条目,简单地说,操作系统把用户界面上的每个操作都转化成为对应的消息,加入消息队列.然后把消息转发给对应的应用程序(一般来说,就是活动窗口),应用程序根据自己的逻辑处理这些消息. 如果应用程序处理某个消息事件的时候,用了很长的时间,这时候后续的消息无法及时得到处理,就会造成应用程序没有响应,也就是常说的"假死"状态. 所以,应用程序如果处理某个事件需要较长的时间,需要把这个操作放到一个另外的线程中进行

学习通过Thread+Handler实现非UI线程更新UI组件

[Android线程机制] 出于性能考虑,Android的UI操作并不是线程安全的,这就意味着如果有多个线程并发操作UI组件,可能导致线程安全问题.为了解决这个问题,Android制定了一条简单的规则:只允许UI线程修改Activity里的UI组件 当一个程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理.所以主线程通常又被叫做UI线程 [H

非UI线程加载图片

Processing Bitmaps Off the UI Thread 非UI线程加载图片 BitmapFactory.decode*一系列方法,在之前的高效加载大图的文章中讲到过. 如果图片的数据源是磁盘,或则网络(内存以外的其他地方),那么解析图片的方法不应该在UI线程中执行.这些数据加载任务所要花费的时间有许多不可控因素,(例如:磁盘读取速度,图片的大小,CPU的频率,等等)如果这些任务阻塞了UI线程,系统判定你的应用程序无响应,用户是有权关闭你的软件的,这样的用户体验非常不好. 这篇文

基础篇-在非UI线程中更新UI元素

个人原创,转载请注明出处: http://blog.csdn.net/supluo/article/details/ 先了解两个概念 1.UI:User Interface的缩写,用户界面的意思.你可以不恰当的理解为我们能够看到的,操作的东西:在Android中什么才称为UI呢,可以简单的理解为View及其子类等元素.这是一个不够正确的概念,只是对新手做一个简单的抛砖引玉. 2.ANR:Application Not Responding,意思是程序没有响应. 在如下情况下,Android会报出

非ui线程更新ui问题

android初学者,刚开始并没有意识到,android中更新UI只能用UI线程,写了一个下载线程,在线程里更新progessbar,并用textview显示下载进度 public void listenProgress(){          new Thread(new Runnable() {                            @Override              public void run() {                  while(progre

学习通过Thread+Handler实现非UI线程更新UI组件(转)

[Android线程机制] 出于性能考虑,Android的UI操作并不是线程安全的,这就意味着如果有多个线程并发操作UI组件,可能导致线程安全问题.为了解决这个问题,Android制定了一条简单的规则:只允许UI线程修改Activity里的UI组件 当一个程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理.所以主线程通常又被叫做UI线程 [H

为什么我们可以在非UI线程中更新UI

尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 炮兵镇楼 看到这样的标题--估计N多人会说我是逗比----因为很多盆友在学习Android(特别是从4.0之后开始入门的)的时候都会常看见或听到别人说我们更新UI呢要在UI线程(或者说主线程)中去更新UI,不要在子线程中更新UI,而Android官方呢也建议我们不要在非UI线程直接更新UI,为什么呢?借助Android官方的一句话来说就是: