在不同的线程上访问Web浏览器

时间:2013-08-10 21:05:17

标签: c# multithreading browser

我想从不同的线程访问静态WebBrowser。

以下是我的示例代码:

public partial class MainFrame : Form
{
    public static WebBrowser webBrowser = new WebBrowser();

     public MainFrame()
     {
         InitializeComponent();
     }
}

class Job
{
    public void Process()
    {
        MainFrame.webBrowser.Navigate("http://www.google.com");
        while (MainFrame.webBrowser.ReadyState != WebBrowserReadyState.Complete)
        {
            Thread.Sleep(1000);
            Application.DoEvents();
        }
    }
}

为简单起见假设我有2个线程。线程1调用Process()函数并等待它完成,因此在此阶段webBrowser应处于完全WebBrowserReadyState模式。

线程1完成后10秒,线程2调用Process()函数。此时如果我调试我的代码并在Process()函数的第一行放置一个BreakPoint并观察MainFrame.webBrowser变量,我会看到:

Debug information of MainFrame.webBrowser

换句话说,它在某种程度上无法进入。任何人都知道这个问题的任何解决方案吗?

  

附加信息:线程1后10秒   完成,如果我再次调用线程1,那么一切都很好。

1 个答案:

答案 0 :(得分:2)

您无法直接从未创建控件的线程调用WebBrowser控件的方法或属性。您需要将此类调用代理到控件的父线程中。一种方法是使用BeginInvoke,但它是异步的。

如果您确实需要同步执行此操作,可以使用SynchronizationContext.Send,如下所示:

public partial class MainFrame : Form
{
    public static WebBrowser webBrowser = new WebBrowser();

    public static System.Threading.SynchronizationContext mainThreadContext = System.Threading.SynchronizationContext.Current;


    public MainFrame()
    {
        InitializeComponent();
    }
}

class Job
{
    public void Process()
    {
        mainThreadContext.Send(delegate 
        {
            MainFrame.webBrowser.Navigate("http://www.google.com");
        }, null);

        bool ready = false;
        while (!ready)
        {
            mainThreadContext.Send(delegate 
            {
                ready = MainFrame.webBrowser.ReadyState != WebBrowserReadyState.Complete;
            }, null);
            Thread.Sleep(1000);
            // if you don't have any UI on this thread, DoEvent is redundant
            Application.DoEvents(); 
        }
    }
}

无论如何,上面的代码对我来说看起来不是一个好设计。你想要实现什么目标?可能有更好的方法。也许,您可以使用WebBrowser.DocumentCompleted事件?