尝试在multithreading应用程序上使用WebBrowser时,我遇到了一些exception。 COM组件,受保护的内存和其他exception,我用WebBrowser做东西。 我只是放弃了,回到我的单线程版本,工作正常。 我会张贴代码,但是当我在这么多的地方得到例外时,很难本地化问题的原因。 因此,如果作为一个单线程应用程序运行良好,并且如果当我运行同一个应用程序的多个实例,它也可以正常工作,应该有一种方法来模拟从单个应用程序运行的几个应用程序,而不必实际做一个分离的应用程序我会从主应用程序运行。 我的问题是,我怎样才能让Windows把我的线程看作是不同的实例呢? 这应该消除这个问题,因为,正如我所说,当他们是不同的实例,我没有得到任何exception。 希望我已经清楚了。
我认为你的问题可能与Microsoft.NET处理UI控件的方式有关。 基本上,控制的任何方法必须从创建它的线程(也许甚至是主UI线程专用)中调用。 否则,你会得到一堆访问相关的异常。 我相信你将需要使用InvokeRequired属性和Invoke方法来调用控件,这也意味着你将不得不定义一个delgate函数来包装你想调用的每个方法。 以WebBroweser.Url属性为例,可以这样写:
public delegate void SetWebAddressDelegate ( WebBrowser browser, Uri newUrl); public void SetWebAddress ( WebBrowser browser, Uri newUrl ) { if (browser.InvokeRequired) browser.Invoke(new SetWebAddressDelegate(SetWebAddress), browser, newUrl); else browser.Url = newUrl; }
WebBrowser是一个COM组件,Internet Explorer。 像许多COM组件一样,它需要一个“单线程的公寓”。 你必须创建一个使其成为组件的好客之家。 基本上有两个基本要求:线程需要被初始化为一个STA,并且需要抽取一个消息循环。
这里有一个使用Windows Forms提供的管道:
private void runBrowserThread(Uri url) { var th = new Thread(() => { var br = new WebBrowser(); br.DocumentCompleted += browser_DocumentCompleted; br.Navigate(url); Application.Run(); }); th.SetApartmentState(ApartmentState.STA); th.Start(); } void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { var br = sender as WebBrowser; if (br.Url == e.Url) { Console.WriteLine("Natigated to {0}", e.Url); Application.ExitThread(); } }
注意在该工作线程上引发了DocumentCompleted事件。 我任意使用该事件也使线程终止。
这听起来像你可能跨线程共享一个WebBrowser实例。 如果每个线程都有自己的实例,并且线程之间没有进行通信,我希望等同于运行多个进程实例。