There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 5011248    Comments: 173    
 日历归档
<<  <  2024 - 03  >  >>
SuMoTuWeThFrSa
     12
3456789
10111213141516
17181920212223
24252627282930
31
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2024年3月28日 星期四 RSS CLI Mine Sweeper. In Javascript.

  在非UI 线程上Show一个含有WebBrowser的Form出现的问题
字体大小 [ ]

问题描述:
客户端的Windows程序使用WebMethod从服务器上取得一个系统信息列表。信息列表中有多条Message。当系统消息的时间合要求,使用一个自定义的MessageForm Show出这个系统Message。MessageForm是一个含有WebBrowser的WinForm。 Show MessageForm的调用在一个Timer中被执行。当调用ShowMessage的操作时会出现下面的错误。
Click to Open in New Window
出错的代码:
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只是为了模拟实际的环境,没有实际意义。

File: 本文示例程序
  Posted @ 7/31/2007 4:20:46 PM | Hits (32854) | Comment (0

  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code