C# 指示方法仅在匿名事件处理程序完成后返回

C# 指示方法仅在匿名事件处理程序完成后返回,c#,C#,在静态方法中,我使用WebBrowser。我正在订阅其导航事件和匿名方法。我是否可以指示我的方法仅在WebBroswer触发导航事件和匿名处理程序完成后返回 using forms = System.Windows.Forms; namespace ProxyProvider { public delegate string finished(); public static class ProxyProvider { public static stri

在静态方法中,我使用WebBrowser。我正在订阅其导航事件和匿名方法。我是否可以指示我的方法仅在WebBroswer触发导航事件和匿名处理程序完成后返回

using forms = System.Windows.Forms;
namespace ProxyProvider
{
    public delegate string finished();
    public static class ProxyProvider
    {
        public static string GetProxy()
        {
            string returnValue = "";
            finished meFinished = () =>
            {
                return returnValue;
            };
            forms.WebBrowser browser = new forms.WebBrowser();
            try
            {
                browser.Navigated += (s, e) =>
                {
                    if (browser.ReadyState == forms.WebBrowserReadyState.Loading) //waiting for browser finishes loading page
                        return;
                    returnValue = ParseHtml(browser.DocumentText); 
                    meFinished();  //I want this function to return only here. After it finishes parsing
                };
                browser.Navigate("http://example.com/proxy-list/");
                return returnValue;  // don't want to return it here
            }
            catch (Exception e)
            {
                forms.MessageBox.Show("ProxyProvider.GetProxy(): " + e.Message);
                return "";
            }
        }
}
}

你可以,但你必须调整一些事情

这里的基本概念是,主方法将阻塞,直到从事件处理程序中设置值为止。由于您目前处于UI线程上,因此希望异步完成此操作(因此您的窗口保持响应)

首先,我们需要更改您的方法的签名:

public static Task<string> GetProxy()
现在您已经完成了,只需返回任务:

browser.Navigate("http://example.com/proxy-list/");
return navTaskSource.Task;
调用代码应该
wait
此方法以避免任何UI线程阻塞并获取返回值

string proxy = await MyClass.GetProxy();

请注意,包含
await
的方法必须标记为
async

无需使该方法
async
。只需直接返回tcs的
任务
。此外,命名TCS
navTask
会产生误导。它不是任务,而是任务的完成源,应该相应地命名。另外,他的方法不是使用
TaskCompletionSource
,而是生成一个
string
,因此它应该是一个
TaskCompletionSource
,在其中设置字符串结果并传递给调用者。最后,此处理程序在被调用一次后取消订阅可能很重要。哦,在您的代码中,如果您在调用
Navigate
(启动任务正在等待的操作)之前正在等待任务,那么代码将死锁。导航需要放在第一位。@servey所有优秀的点。我已经编辑修复(死锁一个非常好,甚至没有注意到)。
string proxy = await MyClass.GetProxy();