42

I'm trying to test the follwing http request method

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

However, the debugger seems to be skipping the code below the 2nd comment. I'm using Visual studio 2015 RC, any ideas? I also tried checking the Tasks window and saw nothing

Edit: Found the solution

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

Turns out that because this was a C# console app it ended after the main thread ends I guess, because after adding a Console.ReadLine() and waiting a bit, the request did return. I guessed that C# would wait until my task execute and not end before it, but I suppose I was wrong. If anybody could elaborate on why this happened it would be nice.

Falle1234
  • 5,013
  • 1
  • 22
  • 29
sgarcia.dev
  • 5,671
  • 14
  • 46
  • 80
  • This is because you have another async method `client.GetAsync(url)`. You should add breakpoint inside that method too. – M.kazem Akhgary Jul 07 '15 at 23:29
  • I should add the breakpoint exactly where? I tried adding breakpoints on every line, even on the one calling my Get method as await, but the debugger still skips anything beyond my second GetAsync call. – sgarcia.dev Jul 07 '15 at 23:32
  • @sgarcia: I believe this question is a duplicate. However, if this is incorrect, then just let me know and I'll reopen. – Stephen Cleary Jul 08 '15 at 00:25
  • @StephenCleary I saw that question but when I saw ASP.NET in the answer I guessed this didn't apply to my question, since I'm doing this on a C# console application. I'll check it out for now, but if the question you pointed out doesn't apply to a C# console app please let me know as well. – sgarcia.dev Jul 08 '15 at 00:28
  • @sgarcia: That answer applies to ASP.NET and UI apps, but not Console apps. A few questions: 1) Are you sure the debugger never hits the `return content` line (i.e., if you put a breakpoint there, it never gets hit)? 2) Are you blocking on the asynchronous code so it has a chance to finish before `Main` exits (and thus the program exits)? 3) If the answers to (1) and (2) are Yes, can you post a minimal, reproducible example? – Stephen Cleary Jul 08 '15 at 00:31
  • Yes, I placed a breakpoint on every single line on code and it never returns. Not sure on question number 2, but my whole app is just this method and a call to it that goes like: Program p = new program(); p.Get(); – sgarcia.dev Jul 08 '15 at 00:34
  • @StephenCleary working on your question #3 – sgarcia.dev Jul 08 '15 at 00:37
  • 2
    @sgarcia: Sounds like your app just isn't waiting before it exits. You need to stop `Main` from exiting. Like do a `p.Get().Wait();` or a `p.Get(); Console.ReadKey();`. – Stephen Cleary Jul 08 '15 at 00:42
  • @StephenCleary Yeah, I actually just figured that out while you wrote that and updated my question with the solution. Sorry about the rookie mistake. Any blog I could check to know why my app isn't waiting for my task to finish even with the await? I tried adding the await to the program.Get() call but it asks me to make the main method async (which I guess isn't the correct way) – sgarcia.dev Jul 08 '15 at 00:45

2 Answers2

70

When Main exits, the program exits. Any outstanding asynchronous operations are canceled and their results discarded.

So, you need to block Main from exiting, either by blocking on the asynchronous operation or some other method (e.g., calling Console.ReadKey to block until the user hits a key):

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

One common approach is to define a MainAsync that does exception handling as well:

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

Note that blocking on asynchronous code is generally considered a bad idea; there are very few cases where it should be done, and a console application's Main method just happens to be one of them.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • 3
    Thanks Stephen. I found using your code fixed my problem too (not for the first time either). It wasn't quite the same as the OP: my debugger stopped before the synchronous execution had even reached the end of `Main()`. I created a `MainAsync` and used `.Wait()`, as per your example and suddenly it all came right. Seems that async code needs to be invoked in strictly the right way. – OutstandingBill Aug 16 '16 at 21:54
  • 1
    Likewise. You should have a bitcoin donation address in your profile. – Sentinel Dec 02 '16 at 08:49
  • I had a similar problem with an async wcf service. Even though my service method was async and I was using await in every async call, when an exception occured, the debug exited silently, I had `try catch` in the code that was faulting, and didn't read there. I just forgot changing my async service method to return `Task` instead of `void`. After this, the exception is caught (it reaches my breakpoint inside `catch` block), and the exception is propagated to the first caller method (which is the one I changed the return from void to task). – Alisson Reinaldo Silva Jan 06 '17 at 11:22
  • @Stephen - I am facing issue in a web application where I am await a method with ConfigureAwait option in an async method then call Wait() on the the task returned and my control(debugger) disappears. I dont understand why. Any comments? – Ashutosh Singh Aug 21 '18 at 11:49
  • @AshutoshSingh: I recommend you ask your own question. I haven't seen the debugger disappear, but asking your own question will make it a lot more visible. – Stephen Cleary Aug 21 '18 at 15:04
  • Sure I am trying to create a sample with same scenario. If same problem appears in sample then I think we can discuss that otherwise if its specific to my project then it may take some time to post exact scenario. Thanks btw. – Ashutosh Singh Aug 21 '18 at 15:06
  • @StephenCleary In sample scenario same setup is working fine but in case of my application its not working..:( – Ashutosh Singh Aug 21 '18 at 15:36
  • @StephenCleary https://stackoverflow.com/questions/51953743/call-to-configureawait-multiple-times-in-call-hierarchy-resulting-into-call-neve Here is the actual issue. – Ashutosh Singh Aug 21 '18 at 17:23
  • thank you thank you and more thanks!! this worked for me – Oswaldo Zapata Mar 24 '20 at 17:30
0

I got the same problem following ChatGPT instructions:

string accountId = "12345";
string apiUrl = $"https://api.example.com/GetDashboards/{accountId}";
HttpResponseMessage response = await _httpClient.GetAsync(apiUrl);  // EXPLODES HERE
response.EnsureSuccessStatusCode();

To fix it I specify the BaseUrl:

using var client = new HttpClient();
client.BaseAddress = new Uri(apiUrl);

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

var urlParameters = "";
var response = await client.GetAsync(urlParameters);
if (response.IsSuccessStatusCode)
{ }
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • I have the same problem using vba.net when i call my web service class from a webMethod aspx. here -> "client.PostAsync(Api, content)" <- is canceled – Carlos Mar 21 '23 at 21:59
  • There is no such thing as VBA.Net it's either VBA in Office Apps or VB.Net – Jeremy Thompson Mar 21 '23 at 22:15
  • Im using vba.net on my page aspx, I call the webMethod and then call the apiRestMethod when call *"client.PostAsync(Api, content)"* here cancel dont show any error just canceled – Carlos Mar 21 '23 at 22:17