Web 浏览器控件 - 等待文档完成扩展方法



我正在为 WebBrowser 控件创建一个扩展方法,其目的是等待页面完成完全加载,然后再返回。

通过完全加载,我的意思是必须在最后一个DocumentCompleted事件之后经过一秒钟。这是为了考虑在页面加载期间触发多个DocumentCompleted事件的页面(这是当前影响我的应用程序的事情)。

我已经编写了当前似乎有效的方法,但我觉得可以改进:它在可能不需要时返回一个任务,并且还存在一个问题,如果应用程序在等待页面加载时关闭,则会引发异常。

    public static Task<bool> WaitLoad(this WebBrowser webBrowser, int wait)
    {
        var timerInternalWait = new Timer {Interval = 1000, Tag = "Internal"};
        var timerMaxWait = new Timer {Interval = wait};
        var tcs = new TaskCompletionSource<bool>();
        WebBrowserNavigatingEventHandler navigatingHandler = (sender, args) => timerInternalWait.Stop();
        webBrowser.Navigating += navigatingHandler;
        WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (sender, args) => { timerInternalWait.Stop(); timerInternalWait.Start(); };
        webBrowser.DocumentCompleted += documentCompletedHandler;
        EventHandler timerHandler = null;
        timerHandler = (sender, args) =>
        {
            webBrowser.Navigating -= navigatingHandler;
            webBrowser.DocumentCompleted -= documentCompletedHandler;
            timerInternalWait.Tick -= timerHandler;
            timerMaxWait.Tick -= timerHandler;
            timerMaxWait.Stop();
            timerInternalWait.Stop();
            tcs.SetResult(((Timer) sender).Tag.ToString() == "Internal");
        };
        timerInternalWait.Tick += timerHandler;
        timerMaxWait.Tick += timerHandler;
        return tcs.Task;
    }

我可以做些什么来改进它吗?

设计准则指出异步方法应带有后缀。

该计时器使您的代码更难阅读。试试这个:

public static Task WaitLoad(this WebBrowser webBrowser)
{
    var tcs = new TaskCompletionSource<object>();
    WebBrowserNavigatingEventHandler navigatingHandler = (sender, args) => timerInternalWait.Stop();
    webBrowser.Navigating += navigatingHandler;
    WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (sender, args) => tcs.SetResult(null);
    try
    {
        webBrowser.DocumentCompleted += documentCompletedHandler;
        await tcs.Task;
    }
    finally
    {
        webBrowser.DocumentCompleted -= documentCompletedHandler;
        await Task.Delay(1000);
    }
    return tcs.Task;
}
public static Task<bool> WaitLoad(this WebBrowser webBrowser, int timeout)
{
    var webBrowserTask = webBrowser.WaitLoad();
    return await Task.WhenAny(webBrowserTask, Task.Delay(timeout)) == webBrowserTask;
}

但是您应该研究取消令牌而不是双计时器。

最新更新