调试器在 Visual Studio 中的异步 HttpClient.GetAsync() 调用后停止

Posted

技术标签:

【中文标题】调试器在 Visual Studio 中的异步 HttpClient.GetAsync() 调用后停止【英文标题】:Debugger stops after async HttpClient.GetAsync() call in visual studio 【发布时间】:2015-07-07 23:23:38 【问题描述】:

我正在尝试测试以下 http 请求方法

public async Task<HttpContent> Get(string url)
    
        using (HttpClient client = new HttpClient())
// breakpoint
        using (HttpResponseMessage response = await client.GetAsync(url))
// can't reach anything below this point
        using (HttpContent content = response.Content)
        
            return content;
        
    

但是,调试器似乎正在跳过第二条注释下方的代码。我正在使用 Visual Studio 2015 RC,有什么想法吗?我还尝试检查“任务”窗口,但什么也没看到

编辑:找到解决方案

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

namespace ConsoleTests

    class Program
    
        static void Main(string[] args)
        
            Program program = new Program();
            var content = program.Get(@"http://www.google.com");
            Console.WriteLine("Program finished");
        

        public async Task<HttpContent> Get(string url)
        
            using (HttpClient client = new HttpClient())
            using (HttpResponseMessage response = await client.GetAsync(url).ConfigureAwait(false))
            using (HttpContent content = response.Content)
            
                return content;
            
        
    

事实证明,因为这是一个 C# 控制台应用程序,我猜它在主线程结束后结束,因为在添加了 Console.ReadLine() 并稍等片刻之后,请求确实返回了。我猜 C# 会等到我的任务执行而不是在它之前结束,但我想我错了。如果有人能详细说明为什么会发生这种情况,那就太好了。

【问题讨论】:

这是因为你有另一个异步方法client.GetAsync(url)。您也应该在该方法中添加断点。 我应该在哪里添加断点?我尝试在每一行上添加断点,即使是在将我的 Get 方法调用为 await 的那一行上,但调试器仍然会跳过我的第二个 GetAsync 调用之外的任何内容。 @sgarcia:我相信这个问题是重复的。但是,如果这不正确,请告诉我,我会重新打开。 @StephenCleary 我看到了这个问题,但是当我在答案中看到 ASP.NET 时,我猜这不适用于我的问题,因为我是在 C# 控制台应用程序上执行此操作的。我现在会检查一下,但如果您指出的问题不适用于 C# 控制台应用程序,请也告诉我。 @sgarcia:听起来您的应用程序在退出之前没有等待。您需要阻止Main 退出。喜欢p.Get().Wait();p.Get(); Console.ReadKey(); 【参考方案1】:

Main 退出时,程序退出。任何未完成的异步操作都将被取消并丢弃其结果。

因此,您需要阻止 Main 退出,方法是阻止异步操作或其他方法(例如,调用 Console.ReadKey 以阻止直到用户按下某个键):

static void Main(string[] args)

  Program program = new Program();
  var content = program.Get(@"http://www.google.com").Wait();
  Console.WriteLine("Program finished");

一种常见的方法是定义一个MainAsync 来处理异常:

static void Main(string[] args)

  MainAsync().Wait();


static async Task MainAsync()

  try
  
    Program program = new Program();
    var content = await program.Get(@"http://www.google.com");
    Console.WriteLine("Program finished");
  
  catch (Exception ex)
  
    Console.WriteLine(ex);
  

请注意,阻塞异步代码通常被认为是一个坏主意;在极少数情况下应该这样做,而控制台应用程序的 Main 方法恰好是其中之一。

【讨论】:

谢谢斯蒂芬。我发现使用你的代码也解决了我的问题(也不是第一次)。它与 OP 不太一样:我的调试器在同步执行甚至到达Main() 的末尾之前就停止了。根据您的示例,我创建了一个MainAsync 并使用了.Wait(),突然一切都好了。似乎需要以严格正确的方式调用异步代码。 同样。您的个人资料中应该有一个比特币捐赠地址。 我在使用异步 wcf 服务时遇到了类似的问题。即使我的服务方法是异步的,并且我在每个异步调用中都使用了 await,但当发生异常时,调试会静默退出,我在出错的代码中有 try catch,并且没有在那里读取。我只是忘记将我的异步服务方法更改为返回Task 而不是void。在此之后,异常被捕获(它到达我在catch 块内的断点),并将异常传播到第一个调用方方法(这是我将返回从 void 更改为 task 的方法)。 @Stephen - 我在 Web 应用程序中遇到问题,我正在等待异步方法中带有 ConfigureAwait 选项的方法,然后在返回的任务上调用 Wait() 并且我的控件(调试器)消失。我不明白为什么。有没有cmets? @AshutoshSingh:我建议你问自己的问题。我还没有看到调试器消失,但问你自己的问题会让它更明显。

以上是关于调试器在 Visual Studio 中的异步 HttpClient.GetAsync() 调用后停止的主要内容,如果未能解决你的问题,请参考以下文章

异步/等待异常和 Visual Studio 2013 调试输出行为

Visual Studio 中的cin操作错误

Windows 8.1 中 Visual Studio 12 中的 OpenCV 错误。这是调试时显示一些错误的简单代码。我怎样才能解决这个问题?

Visual Studio 2012 中的远程调试

立即窗口 VIsual studio 调试 undefined

附加 Visual Studio 调试器会导致高 CPU 使用率和 UI 线程锁定