如何同步访问webbrowser.navigate

时间:2014-09-28 15:36:17

标签: c# winforms

如何在代码中从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;
}

1 个答案:

答案 0 :(得分:0)

有几种方法可以支持这一点。一种方法是简单地将异步操作封装在一个方法中,使用同步原语来阻塞线程,直到操作异步完成(警告:未测试):

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提到的)并简单地调用{ {1}}(警告:未经过测试):

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; } 的方法,因为它可以更好地模拟您所拥有的是异步操作以及您实际等待以完成它的事实。此外,您可以在UI中异步使用它:

Task