簡體   English   中英

WebBrowser是否有Application.DoEvents()?

[英]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),可以通過TaskCompletionSourceawait輕松完成此操作

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM