繁体   English   中英

如何同步访问webbrowser.navigate

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM