![](/img/trans.png)
[英]Why doesn't Application.DoEvents() allow the WebBrowser Control to process
[英]is there an Application.DoEvents() for WebBrowser?
我正在使用一個Timer
來確定使用AJAX加載的頁面是否准備就緒,並且僅在准備就緒時才從函數返回(包括ajax內容的頁面加載已加載)。 我正在嘗試下面的代碼,但我發現Application.DoEvents()
僅處理未決的Windows消息循環項,因此它會陷入無限循環,因為Applicadion.DoEvents()
不會引發任何WebBrowser的事件(僅Windows)正如我提到的那樣),因此ReadyState
無法更新,也永遠不會改變。
我的問題是:有什么方法可以強制WebBrowser's
事件Application.DoEvents()
執行嗎?
static bool done = false;
int[] foo()
{
int[] data;
timer1.Interval = 1000;
timer1.Tick += new EventHandler(delegate(object o, EventArgs ea)
{
if (browser.ReadyState == WebBrowserReadyState.Complete)
{
timer1.Stop();
data = extract_data();
done = true;
}
});
timer1.Start();
while(!done) /* return from function only if timer1 isn't running anymore */
{
Application.DoEvents();
Thread.Sleep(1000);
}
return data;
}
我知道Application.DoEvents()
“問題”,但是找不到其他方法。 也非常歡迎采用其他方法來解決這一問題。
如果您使用的是.NET 4.5或更高版本(如果您願意使用Microsoft.Bcl.Async庫,則為4.0),可以通過TaskCompletionSource
和await
輕松完成此操作
async Task<int[]> foo()
{
//Create the completion source and the callback delegate.
var tcs = new TaskCompletionSource<object>();
WebBrowserDocumentCompletedEventHandler callback = (sender, args) => tcs.SetResult(null);
//Subscribe to the Document completed event and run the callback.
browser.DocumentCompleted += callback;
try
{
//We may already be in the complete state so the event will never fire.
//Therefor if we are in the completed state we can skip the await.
if (browser.ReadyState != WebBrowserReadyState.Complete)
{
//Wait here for the completed event to fire.
await tcs.Task;
}
}
finally
{
//Unsubscribe the callback which is nolonger needed.
browser.DocumentCompleted -= callback;
}
//Process the data from the completed document.
var data = extract_data();
return data;
}
此代碼將執行的操作是訂閱DocumentCompleted
事件,然后在尚未完成加載的情況下有選擇地等待文檔完成,而正在等待它將控制權返回給調用方(與DoEvents循環的效果相同,但效果要好得多) )一旦事件觸發,它將處理數據並返回結果。
但是,如果可能的話,一個更好的解決方案是重新編寫代碼,以完全不調用foo
,而只訂閱DocumentCompleted
事件,然后將數據推送到需要處理的位置而不是拉出數據。
在Visual Studio中,雙擊WebBrowser控件。 這將為DocumentCompleted事件創建一個事件處理程序。 您可以使用任何其他機制來創建DocumentCompleted事件處理程序,但是該事件很重要。 有關示例,請參閱我的文章“網站爬網簡介” 。
請不要為此使用Application.DoEvents(),ReadyState或Thread.Sleep。
如果網頁使用腳本來生成頁面的一部分,則解決該問題可能會很復雜。 如果發生這種情況,那么我將盡一切可能避免使用Thread.Sleep,但您可能必須這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.