[英]How to synchronously access webbrowser.navigate
从webbrowser导航后如何获取html,如下代码所示。 这是一个可以在其他项目中使用的dll库,它不是winforms。 调用导航后,它不会等待。
public List<Category> Categories;
public WebBrowser Browser;
public List<Category> ListAllCategories()
{
Browser.DocumentCompleted += ReadAllCategories;
Browser.Navigate(CoursesLink);
//want to wait here until categories are built in the ReadAllCategories method without wasting CPU cycles
return Categories;
}
void ReadAllCategories(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
switch (browser.ReadyState)
{
case WebBrowserReadyState.Complete:
if (browser.Document != null)
{
//buildingListofCategories
}
break;
case WebBrowserReadyState.Interactive:
break;
case WebBrowserReadyState.Loaded:
break;
case WebBrowserReadyState.Loading:
break;
case WebBrowserReadyState.Uninitialized:
break;
default:
break;
}
browser.DocumentCompleted -= ReadAllCategories;
}
有两种方法可以支持这一点。 一种方法是简单地将异步操作封装在一种方法中,该方法使用同步原语来阻塞线程,直到该操作异步完成( 警告:未测试 ):
public List<Category> GetAllCategories(Uri CoursesLink)
{
List<Category> categories = new List<Category>();
ManualResetEventSlim waitEvent;
using (WebBrowser browser = new WebBrowser())
{
waitEvent = new ManualResetEventSlim();
browser.DocumentCompleted += (s, e) =>
{
switch (browser.ReadyState)
{
case WebBrowserReadyState.Complete:
// TODO: your processing, filling categories
waitEvent.Set();
break;
// TODO: error processing
}
};
browser.Navigate(CoursesLink);
}
waitEvent.Wait(); // TODO: timeout?
return categories;
}
当然,另一种方法是使用.NET中的内置Task
支持在Task
对象(类似于Schabse提到的对象)中建模固有的异步任务,并简单地调用Wait
( 警告:未测试 ):
public Task<List<Category>> GetAllCategoriesAsync(Uri CoursesLink)
{
var tcs = new TaskCompletionSource<List<Category>>();
List<Category> categories = new List<Category>();
using (WebBrowser browser = new WebBrowser())
{
browser.DocumentCompleted += (s, e) =>
{
switch (browser.ReadyState)
{
case WebBrowserReadyState.Complete:
// TODO: your processing, filling categories
tcs.SetResult(categories);
break;
// TODO: error processing
}
};
browser.Navigate(CoursesLink);
}
return tcs.Task;
}
//...
public List<Category> ListAllCategories()
{
return GetAllCategoriesAsync(CoursesLink).Result;
}
我建议使用基于Task
的方法,因为它可以更好地模拟以下事实:您拥有的是异步操作,并且您实际上正在等待它完成。 此外,您还可以在UI中异步使用它:
var categories = await GetAllCategoriesAsync(CoursesLink);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.