我在控制台应用程序中使用 System.Windows.Forms.WebBrowser 来呈现网页,然后在其上调用脚本。为了呈现网页,我使用 Application.DoEvents 来加载和执行脚本。
但是有时应用程序会在调用 Application.DoEvents 时挂起。我找不到任何理由。我不认为我在事件循环上造成死锁。
网络上的许多人说根本不应该使用 Application.DoEvents,因为它产生的问题多于解决的问题。所以我认为必须有一个替代方案。但是我搜索了很多,没有找到 Application.DoEvents 的替代方案。
有人知道吗?任何信息表示赞赏。先感谢您!
感谢 Noseratio 的帮助,我完成了代码的起草,但仍然存在冻结问题。
以下面的代码为例(代码太长,所以我把它粘贴在 pastebin 上): http: //pastebin.com/DkDcrirU
当您运行此代码时,偶尔会出现至少一个窗口无法关闭。如果你附加到冻结的进程,你会发现代码卡在下面一行(由“>>>”表示):
public static bool NavigateLoadAndRender(WebBrowserContext browserContext, string url, TimeSpan loadTimeout, TimeSpan renderTime, out string errMsg)
{
ForceInitActiveXInstance(browserContext);
object axi = null;
Func<Uri> getBrowserUri = null;
Action<Uri> navigateBrowser = null;
Func<IHTMLDocument2> getBrowserDoc = null;
switch (browserContext.WebBrowserType)
{
case WebBrowserTypeEnum.Forms:
{
var browser = browserContext.GetWebBrowserAsFormsType();
getBrowserUri = () => browser.Url;
navigateBrowser = u =>
{
var finished = false;
browserContext.SyncContext.Post(state =>
{
browser.Navigate(u);
finished = true;
}, null);
while (!finished) Thread.Sleep(DefaultConfig_SyncContextPostCheckInterval);
};
getBrowserDoc = () =>
{
IHTMLDocument2 doc = null;
bool finished = false;
browserContext.SyncContext.Post(state =>
{
doc = (IHTMLDocument2)browser.Document.DomDocument;
finished = true;
}, null);
>>> while (!finished) Thread.Sleep(DefaultConfig_SyncContextPostCheckInterval);
return doc;
};
axi = GetActiveXInstance(browserContext);
}
break;
case WebBrowserTypeEnum.Wpf:
{
var browser = browserContext.GetWebBrowserAsWpfType();
axi = GetActiveXInstance(browser);
getBrowserUri = () => browser.Source;
navigateBrowser = u =>
{
var finished = false;
browserContext.SyncContext.Post(state =>
{
browser.Navigate(u);
finished = true;
}, null);
while (!finished) Thread.Sleep(DefaultConfig_SyncContextPostCheckInterval);
};
getBrowserDoc = () =>
{
IHTMLDocument2 doc = null;
bool finished = false;
browserContext.SyncContext.Post(state =>
{
doc = (IHTMLDocument2)browser.Document;
finished = true;
}, null);
while (!finished) Thread.Sleep(DefaultConfig_SyncContextPostCheckInterval);
return doc;
};
axi = GetActiveXInstance(browserContext);
}
break;
default: throw new ArgumentException("unknown browser type", browserContext.WebBrowserType.ToString());
}
var success = NavigateLoadAndRender(
axi, url,
getBrowserUri,
navigateBrowser,
//() => DoEvents(browser),
getBrowserDoc,
loadTimeout, renderTime, out errMsg);
return success;
}
有谁知道发生了什么?