问题描述
我正在为 WebBrowser
控件创建一个扩展方法,其目的是等待页面完成完全加载后再返回.
I'm creating an extension method for the WebBrowser
control whose purpose is to wait for the page to have finished completely loading before returning.
通过完全加载,我的意思是最后一次 DocumentCompleted
事件发生后必须经过一秒钟.这是为了解决在页面加载过程中触发了多个 DocumentCompleted
事件的页面(目前正在影响我的应用程序).
By completely loading, I mean that one second has to have elapsed after the last DocumentCompleted
event. This is to account for pages where multiple DocumentCompleted
events are triggered during the loading of the page (which is something that's affecting my app currently).
我已经编写了当前的方法,该方法似乎可以工作,但是我觉得可以改进:它可能在不需要时返回任务,并且还存在以下问题:如果关闭应用程序,则会引发异常等待页面加载.
I've written the current method which appears to work but I feel like could be improved: it returns a task when there's probably no need and also it suffers from the problem that an exception will be thrown if the application is closed down while it is waiting for the page to load.
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;
}
我可以做些什么来改善它吗?
Is there something I can do to improve it?
推荐答案
该计时器使您的代码难以阅读.尝试以下方法:
That timer is making your code harder to read. Try this instead:
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;
}
但是您应该研究取消令牌,而不是重复计时器.
But you should look into cancellation tokens instead of double timers.
这篇关于WebBrowser控件-等待文档完成扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!