MultiThreading WebBrowser控件C#STA

时间:2009-08-09 14:30:39

标签: c# multithreading webbrowser-control

我想创建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全部初始化,一切看起来都不错,但只有一两个实际上会做任何事情而且它永远不会一致。线程一直是个噩梦。任何人都可以提出一个不错的选择吗?

4 个答案:

答案 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");
}