2015-12-02 21 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 
}