老读者,第一次张贴在这里。
我的目标:能够在使用 WebBrowser 类时利用 async/await。由于 WebBrowser.Navigate(string url) 是一种异步方法,在触发 LoadComplete 事件之前您无法检查 html 文档。
到目前为止,这是我的(工作)代码:
public class AsyncWebBrowser
{
protected WebBrowser m_WebBrowser;
private ManualResetEvent m_MRE = new ManualResetEvent(false);
public void SetBrowser(WebBrowser browser) {
this.m_WebBrowser = browser;
browser.LoadCompleted += new LoadCompletedEventHandler(WebBrowser_LoadCompleted);
}
public Task NavigateAsync(string url) {
Navigate(url);
return Task.Factory.StartNew((Action)(() => {
m_MRE.WaitOne();
m_MRE.Reset();
}));
}
public void Navigate(string url) {
m_WebBrowser.Navigate(new Uri(url));
}
void WebBrowser_LoadCompleted(object sender, NavigationEventArgs e) {
m_MRE.Set();
}
}
之前的类(class)现在允许我使用以下内容:
public async void NavigateToGoogle() {
await browser.NavigateAsync("www.google.com");
//Do any necessary actions on google.com
}
但是,我想知道是否有更有效/更正确的方法来处理这个问题。具体来说,Task.Factory.CreateNew 与阻塞 ManualResetEvent。感谢您的意见!
最佳答案
首先,我认为这是学习 async/await 工作原理的一个很好的练习。
为了让 NavigateAsync 返回一个任务,您似乎在跳过各种障碍。但它不必为了等待而返回任务! 包含 await 的方法必须返回 Task,但可等待 的方法不需要返回 Task;它所要做的就是返回一些你可以调用 GetAwaiter 的类型。
你可能会考虑像这样实现一个小类型:
public struct WebBrowserAwaiter<T>
{
public bool IsCompleted { get { ... } }
public void OnCompleted(Action continuation) { ... }
public T GetResult() { ... }
}
并让 NavigateAsync 返回某种类型,您可以根据该类型调用返回 WebBrowserAwaiter 的 GetAwaiter。当您可以创建自己的方法时,无需构建 Task 来获取其 GetAwaiter 方法。
更一般地说,您可能想考虑的是如果在第一个仍在导航时第二次调用 NavigateAsync 会发生什么情况?
关于c# - .NET 的 WebBrowser 类的异步/等待实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8610197/