【问题标题】:Call HttpClient.GetAsync in console application - Deadlock在控制台应用程序中调用 HttpClient.GetAsync - 死锁
【发布时间】:2018-08-22 11:57:01
【问题描述】:

我搜索并看到了很多帖子,但我不知道为什么这个简单的控制台调用使用 httpclient.getasync 并等待它会导致它无法完成。这是代码:

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class Program
{
    public static void Main(string[] args)
    {
        GetAPI().Wait();
        Console.WriteLine("Hello");
        //Console.ReadLine();
    }

    public static async Task GetAPI()
    {
        using (HttpClient client = new HttpClient())
        {
            var response = await client.GetAsync("https://www.google.com/");
            //var response = client.GetAsync("https://www.google.com/").Result

            string content = await response.Content.ReadAsStringAsync();
            Console.WriteLine(content);
        }
    }
}

如果我改用 client.GetAsync("https://www.google.com/").Result;并删除“等待”(请参阅​​注释掉的代码)它会起作用,但是我相信这是不可以的,因为我正在将异步函数转换为同步函数。我看过其他关于此的帖子和博客,它们都声称我正在尝试做的事情是正确的,但是在运行示例应用程序时,结果却并非如此。

【问题讨论】:

  • 这可能是一个死锁问题,但我试图通过在 GetAPI 调用中不调用 .Result 来避免它。我正在尝试使用 async 和 await 来防止死锁。我只在控制台程序的 main 函数中使用了 wait() ,它需要阻止以防止程序退出。您链接的其他线程都在调用 Result ,这是我避免的。
  • 这个应用程序不应该死锁(我什至试过了——它不适合我)。

标签: c# .net async-await dotnet-httpclient


【解决方案1】:

您可以在Main 中拨打wait()

但请注意,这只适用于console applications,并且会在 ASP.NET、WPF、WinForms 等 UI 应用程序中死锁...

public void Main(string[] args)
{

    try
    {           
         var t =  GetAPI();
         t.Wait();
         Console.WriteLine(t.Result);   
    }
    catch (Exception ex)
    {
         Console.WriteLine(ex.Message);  
    }

}

public static async Task<string> GetAPI()
{
   using (HttpClient client = new HttpClient())
   {
      var response = await client.GetAsync("https://www.google.com/"); 
      string content = await response.Content.ReadAsStringAsync(); 

     return content;
   }
}

MSDN

此代码在控制台应用程序中可以正常工作,但会 从 GUI 或 ASP.NET 上下文调用时出现死锁。

【讨论】:

    【解决方案2】:

    问题是等待client.GetAsync,得到结果后等待主线程空闲,主线程等待client.GetAsync完成。

           var response = await client.GetAsync("https://www.google.com/").ConfigureAwait(false);
           string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    

    会告诉client.GetAsync在其他线程上完成,然后将结果返回给主线程,这样就不会再出现死锁了。

    【讨论】:

    • 这似乎已经成功了,我想我也看到了另一个线程的这个建议,但是当我应用它时由于某种原因它不起作用。我必须回去确保没有其他“同步”调用阻止它工作。
    猜你喜欢
    • 2021-12-14
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    相关资源
    最近更新 更多