我想从不同的线程访问静态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
变量,我会看到:
换句话说,它在某种程度上无法进入。任何人都知道这个问题的任何解决方案吗?
附加信息:线程1后10秒 完成,如果我再次调用线程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事件?