C# 如何同步访问webbrowser.navigate

C# 如何同步访问webbrowser.navigate,c#,winforms,C#,Winforms,如何在从webbrowser导航后获得html,如下面的代码所示。这是一个可以在其他项目中使用的dll库,而不是winforms。调用navigate后,它不会等待 public List<Category> Categories; public WebBrowser Browser; public List<Category> ListAllCategories() { Browser.DocumentCompleted += ReadAllCategorie

如何在从webbrowser导航后获得html,如下面的代码所示。这是一个可以在其他项目中使用的dll库,而不是winforms。调用navigate后,它不会等待

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;
}

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

我建议使用基于任务的方法,因为它可以更好地模拟这样一个事实,即您拥有的是一个异步操作,并且您实际上正在等待它完成。此外,您还可以在UI中异步使用它:

var categories = await GetAllCategoriesAsync(CoursesLink);

您需要使用异步并构建自己的任务。不,我碰巧就是这样做的。我将编辑答案以反映这一点。ListAllCategories方法属于接口,已标记为[OperationContract]属性。那么,这和它的工作原理是一样的吗?确定OperationContractAttribute只是使类的一个成员与WCF中服务契约中的一个操作相关联。您不需要使用wait,因为您希望它是同步的,所以不需要用async修饰listalCategories,这样它就不会引起任何问题,只需要花一段时间,并且需要执行错误处理:。我已经更新了答案以显示ListAllCategories实现。
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;
}
var categories = await GetAllCategoriesAsync(CoursesLink);