我在屏幕外ChromiumWebBrowser
,用于在页面上运行一些JS并获取结果。
Load方法是同步的,但是在引发FrameLoadEnd事件之前,我无法运行JS代码,这意味着或我的目的Load是一个以FrameLoadEnd事件结尾的异步方法。
为了使代码更清晰,我尝试创建一种扩展方法,该方法将允许我等待页面加载使用,await
而不是注册事件。但是,当我将此方法与TaskCompletionSource一起使用时,原本应该在页面加载后运行的javascript没有加载,但是当使用anAutoResetEvent
并等待它运行时,代码确实起作用。
该代码不起作用:
public static Task LoadPageAsync(this IWebBrowser browser, string address)
{
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
browser.FrameLoadEnd += (sender, args) =>
{
if (args.IsMainFrame)
{
tcs.TrySetResult(true);
}
};
browser.Load(address);
return tcs.Task;
}
这样做:
public static AutoResetEvent LoadPageAsync(this IWebBrowser browser, string address)
{
AutoResetEvent are = new AutoResetEvent(false);
browser.FrameLoadEnd += (sender, args) =>
{
if (args.IsMainFrame)
{
are.Set();
}
};
browser.Load(address);
return are;
}
这是调用代码:
await _browser.LoadPageAsync("Some web address");
LoadScripts();
DoJsThing();
GetJsData();
他们做同样的事情,但是我觉得返回任务比返回AutoResetEvent时,该函数的意图要清晰得多。
为什么不能使用TaskCompletionSource表示我完成了?难道我做错了什么?
public static Task LoadPageAsync(IWebBrowser browser, string address = null)
{
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
EventHandler<LoadingStateChangedEventArgs> handler = null;
handler = (sender, args) =>
{
//Wait for while page to finish loading not just the first frame
if (!args.IsLoading)
{
browser.LoadingStateChanged -= handler;
//Important that the continuation runs async using TaskCreationOptions.RunContinuationsAsynchronously
tcs.TrySetResult(true);
}
};
browser.LoadingStateChanged += handler;
if (!string.IsNullOrEmpty(address))
{
browser.Load(address);
}
return tcs.Task;
}
请注意,我用LoadingStateChanged
它来更好地指示整个页面何时完成加载。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句