我想创建3个线程,每个线程运行WebBroswer控件。所以我想使用ThreadPool让事情变得简单。
for(int i = 0;i < 3;i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(gotoWork), i));
}
WaitAll(waitHandles);
...... /
void gotoWork(object o)
{
string url = String.Empty;
int num = (int)o;
switch(num)
{
case 0:
url = "google.com";
break;
case 1:
url = "yahoo.com";
break;
case 2:
url = "bing.com";
break;
}
WebBrowser w = new WebBrower();
w.Navigate(url);
}
但是我得到一个错误,说我需要一个ThreadPool永远不会的STA线程。在尝试这种方法之前,我试过了。
Thread[] threads = Thread[3];
for(int i = 0;i < 3;i++)
{
threads[i] = new Thread(new ParameterizedStart(gotoWork);
threads[i] = SetApartmentState(ApartmentState.STA); //whoo hoo
threads[i] = Start();
}
for(int i = 0; i < 3;i++)
{
threads[i].Join();
}
WebBrowsers全部初始化,一切看起来都不错,但只有一两个实际上会做任何事情而且它永远不会一致。线程一直是个噩梦。任何人都可以提出一个不错的选择吗?
答案 0 :(得分:0)
您需要在某个地方托管webbrowser控件才能使其工作(将其添加到表单中),其次您应该使用主机控件(或类似委托)的Invoke()(如Form.Invoke())进行交互WebBrowser控件。
现在无需提醒,但是,您的主题应该是STA
答案 1 :(得分:0)
您可以使用此类类来托管WebBrowser控件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SomeNameSpace
{
public class WebForm : Form
{
public WebBrowser WebBrowser { get; set; }
public WebForm()
{
WebBrowser = new WebBrowser();
}
}
}
答案 2 :(得分:0)
毕竟我选择了这个解决方案: http://watin.sourceforge.net/documentation.html
在你的情况下你应该这样做:
...
Thread thread = new Thread(SomeMethod);
thread.SetApartmentState(ApartmentState.STA);
...
答案 3 :(得分:0)
public sealed class SiteHelper : Form
{
public WebBrowser mBrowser = new WebBrowser();
ManualResetEvent mStart;
public event CompletedCallback Completed;
public SiteHelper(ManualResetEvent start)
{
mBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(mBrowser_DocumentCompleted);
mStart = start;
}
void mBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// Generated completed event
Completed(mBrowser);
}
public void Navigate(string url)
{
// Start navigating
this.BeginInvoke(new Action(() => mBrowser.Navigate(url)));
}
public void Terminate()
{
// Shutdown form and message loop
this.Invoke(new Action(() => this.Close()));
}
protected override void SetVisibleCore(bool value)
{
if (!IsHandleCreated)
{
// First-time init, create handle and wait for message pump to run
this.CreateHandle();
this.BeginInvoke(new Action(() => mStart.Set()));
}
// Keep form hidden
value = false;
base.SetVisibleCore(value);
}
}
另一个班级为
public abstract class SiteManager : IDisposable
{
private ManualResetEvent mStart;
private SiteHelper mSyncProvider;
public event CompletedCallback Completed;
public SiteManager()
{
// Start the thread, wait for it to initialize
mStart = new ManualResetEvent(false);
Thread t = new Thread(startPump);
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
mStart.WaitOne();
}
public void Dispose()
{
// Shutdown message loop and thread
mSyncProvider.Terminate();
}
public void Navigate(string url)
{
// Start navigating to a URL
mSyncProvider.Navigate(url);
}
public void mSyncProvider_Completed(WebBrowser wb)
{
// Navigation completed, raise event
CompletedCallback handler = Completed;
if (handler != null)
{
handler(wb);
}
}
private void startPump()
{
// Start the message loop
mSyncProvider = new SiteHelper(mStart);
mSyncProvider.Completed += mSyncProvider_Completed;
Application.Run(mSyncProvider);
}
}
class Tester :SiteManager
{
public Tester()
{
SiteEventArgs ar = new SiteEventArgs("MeSite");
base.Completed += new CompletedCallback(Tester_Completed);
}
void Tester_Completed(WebBrowser wb)
{
MessageBox.Show("Tester");
if( wb.DocumentTitle == "Hi")
base.mSyncProvider_Completed(wb);
}
//protected override void mSyncProvider_Completed(WebBrowser wb)
//{
// // MessageBox.Show("overload Tester");
// //base.mSyncProvider_Completed(wb, ar);
//}
}
在您的主表单上:
private void button1_Click(object sender, EventArgs e)
{
//Tester pump = new Tester();
//pump.Completed += new CompletedCallback(pump_Completed);
//pump.Navigate("www.cnn.com");
Tester pump2 = new Tester();
pump2.Completed += new CompletedCallback(pump_Completed);
pump2.Navigate("www.google.com");
}