http客户端冻结在Windows窗体应用程序中

bto*_*rdz 0 c# httpclient async-await asp.net-web-api

我正在关注这个例子,它可以在一个控制台应用程序中运行,但后来我在一个Windows窗体应用程序中尝试了它并且它会在命中行时await client.GetAsync("api/branches/1035") 如何不同?

控制台代码(这是有效的):

static void Main()
    {
        RunAsync().Wait();
    }

    static async Task RunAsync()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("http://localhost:49358/");

           client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage response = await client.GetAsync("api/branches/1035");

            if (response.IsSuccessStatusCode)
            {
                branch branch = await response.Content.ReadAsAsync<branch>();
                Console.WriteLine("{0}\t${1}", branch.Id, branch.Color);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

当它击中时它会被冻结 await client.GetAsync("api/branches/1035")

private void button1_Click(object sender, EventArgs e)
    {
        RunAsync().Wait();
    }

    static async Task RunAsync()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("http://localhost:49358/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage response = await client.GetAsync("api/branches/1035");

            if (response.IsSuccessStatusCode)
            {
                Branch branch = await response.Content.ReadAsAsync<Branch>();
                Console.WriteLine("{0}\t${1}", branch.Id, branch.Color);
            }

        }
    }
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 5

你看到了我在博客上完全解释的僵局.本质上,一个await将捕获"上下文"并使用它来恢复该async方法.在Console应用程序中,此"上下文"是线程池上下文,但在UI应用程序中,此"上下文"是UI线程上下文.

进一步调用堆栈,你正在调用Wait,它阻塞该线程直到任务完成.在Console应用程序中,该async方法在线程池线程上恢复; 但是在UI应用程序中,该async方法无法在UI线程上恢复(因为UI线程在调用中被阻止Wait).

要解决此问题,请一直使用async:

private async void button1_Click(object sender, EventArgs e)
{
  await RunAsync();
}
Run Code Online (Sandbox Code Playgroud)