我正在为 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;
}
但是您应该研究取消令牌而不是双计时器。