2015-12-02 19 views
0

我正在重寫一些使用WebBrowser對象的代碼來確定服務器何時準備好下載文件。總的來說,這種行爲是這樣的,首先將文件上傳到服務器,一旦上傳服務器,然後開始工作,因爲它正在進行工作,它將連接到它服務的特定頁面的用戶重定向到各種URL直到它完成,一次完成後文件就可以下載了。處理任務中的事件;在任務中處理來自WebBrowser的導航事件?

我想所有的這種行爲在一個單一的函數調用,基本上GetFileFromServer()。一旦這個調用返回,那麼文件就在指定的文件路徑中。

問題是,當使用WebBrowser我必須處理Navigated事件以確定文件何時可以下載,這將使程序流離開GetFileFromServer函數。我可能只是有一個小while循環

while(fileNotDownloaded) 
    Thread.Sleep(500); 

但我想用一個Task代替該功能看起來像

public void GetFileFromServer() 
{ 
    UploadFile(); // Blocks until file is uploaded 
    DownloadFile(); // Blocks until file is downloaded 
} 

我已經實現UploadFile但同樣,因與問題DownnloadFile。基本上我想我的功能看起來像這樣

private void DownloadFile() 
{ 
    var DoWebDriverTask = Task.Factory.StartNew(() => 
    { 
     Boolean fileReady = false; 
     WebBrowser webBrowser = new WebBrowser(); 
     webBrowser.Url = new Uri(MySpecificIP); 
     webBrowser.Navigated += WebBrowserNavigated; 

     // Sit and Spin until the specific URL is navigated to 
     while(!fileReady) 
      Task.WaitAll(new Task[] { Task.Delay(500) }); 

     DownloadFile(); 

     private void WebBrowserNavigated(object sender, WebBrowserNavigatedEventArgs e) 
     { 
      if(e.Url.AbsoluteUri.ToString().Contains("mySpecificURLString")) 
       fileReady = true; 
     } 
    }, CancelWaitForDownloadTaskToken); 
    Task.WaitAll(new Task[] { WebDriverTask }); 
} 

但是,這顯然是不正確的代碼。我也明白這是我上面提供的同樣的解決方案,但只是搬進了Task,但它確實給了我想要的GetFileFromServer以外的行爲。請注意,UI線程中沒有這樣的情況,因此,我上面提供的解決方案仍然可行...但使用Task如果用戶希望,我可以取消等待下載。

那麼我是否有辦法處理Task中的事件Navigated,正如我在上面的代碼中所描述的那樣?

+0

我認爲你應該使用[TaskCompletionSource(https://msdn.microsoft.com/en-us/library/dd449174%28v=vs.110%29.aspx) –

+0

或者您可以將'WebBrowserNavigated'轉換爲lambda表達式。但使用'TaskCompletionSource'更好。 –

回答

1

這裏是如何在方法的範圍相同處理該事件:

webBrowser.Navigated += (s, e) => 
{ 
    if (e.Url.AbsoluteUri.ToString().Contains("mySpecificURLString")) 
     fileReady = true; 
}; 

然而,循環和等待是不是一個很好的主意,這裏是一個更好的選擇:

private Task WaitBeforeDownloadFile(WebBrowser webBrowser) 
{ 
    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); 

    WebBrowserNavigatedEventHandler web_browser_on_navigated = null; 

    web_browser_on_navigated = (s, e) => 
    { 
     if (e.Url.AbsoluteUri.ToString().Contains("mySpecificURLString")) 
     { 
      tcs.TrySetResult(true); 

      webBrowser.Navigated -= web_browser_on_navigated; 
     } 
    }; 

    webBrowser.Navigated += web_browser_on_navigated; 

    return tcs.Task; 
} 

此方法創建一個Task,當引發Navigated事件並滿足您指定的條件時,該方法完成。

這裏是你將如何使用它:

private void DownloadFile() 
{ 
    WebBrowser webBrowser = new WebBrowser(); 
    webBrowser.Url = new Uri(MySpecificIP); 

    //Initiate whatever here before waiting for the Navigated event 

    WaitBeforeDownloadFile(webBrowser).Wait(); 

    //Continue here 
} 

這又不是做一個非常好的事情。但是,既然你想要一個同步行爲,那麼你必須這樣做。

一個更好的替代方法,需要對事情做很多改變,就是異步做事,這需要大量的學習。這裏有一個例子:

public async Task GetFileFromServer() 
{ 
    await UploadFile(); 
    await DownloadFile(); 
} 

public async Task UploadFile() 
{ 
    ... 
} 

public async Task DownloadFile() 
{ 
    WebBrowser webBrowser = new WebBrowser(); 
    webBrowser.Url = new Uri(MySpecificIP); 

    //Initiate whatever here before waiting for the Navigated event 

    await WaitBeforeDownloadFile(webBrowser); 

    //Continue here 
}