【发布时间】:2016-03-16 21:19:17
【问题描述】:
我正在为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;
}
有什么可以改进的吗?
【问题讨论】:
-
显然在开始导航和函数 WaitLoad 订阅事件 WebBrowser.DocumentCompleted 之间有一段时间。如果在订阅事件之前引发事件 DocumentCompleted 会发生什么?
-
从here检查
NavigateAsync。 -
@HaraldDutch 在我问了这个问题之后,我自己意识到了这一点。虽然像 Noseratio 提出的解决方案有助于显式导航,但 Click() 并等待页面重新加载呢?因此,我将改为为 WebBrowser 控件创建一个包装器,这样事件订阅的持续时间与对象实例的持续时间一样长。
-
@Noseratio,如上面的评论中所述,您的答案仅适用于导航异步,而不适用于例如单击导致新页面加载的按钮的情况。另外,我不得不承认我不是投票的忠实拥护者——如果您进行投票,甚至使用
DocumentCompleted也毫无意义。除了页面可能完成(发出DocumentCompleted),然后发出重定向,当浏览器到达新服务器时,DOM 保持不变超过 500 毫秒,使用您的方法会错误地返回已完成导航。 -
@Noseratio,换句话说,我发现解决上述评论中问题的唯一方法是利用
DocumentCompleted和Navigating事件。轮询 DOM 以获取更改永远不会可靠地工作。
标签: c# .net async-await webbrowser-control