c# - .NET 的 WebBrowser 类的异步/等待实现

标签 c# .net asynchronous browser async-await

老读者,第一次张贴在这里。

我的目标:能够在使用 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/

相关文章:

C# 生成新线程然后等待

c# - SelectSingleNode 使用 XPath 为已知良好的 xml 节点路径返回 null

c# - Windows 中的蓝牙 AVRCP 命令会触发哪些事件

c# - 为什么无法解析来自程序集的类型 CaSTLe Windsor

c# - 不使用数据集通过 Web 服务传输数据库查询

c# - 在 .NET Standard 库中访问 Dispatcher IScheduler

c# - 如何使用 IList 上的 LINQ 扩展来查询嵌套对象中的值?

javascript - 检查文件是否存在,如果存在则返回

python - 非 Web、非文件应用程序中的异步性能

javascript - 在异步代码中运行同步代码 - promise