0

I have a basic .Net Winform desktop application. I'd like to make multiple http calls to an Api from the application, one http call takes about 50s to complete, let's call the method GetApiDataAsync() . I want to call GetApiDataAsync() 500+ times. Synchronous would be too slow so my goal is to run as many as I can in parallel. I've done this by creating a list of tasks and awaiting it ( var results = await Task.WhenAll(taskList) ) but I've noticed that when the size of the list takes greater than about 1.5 min I get an exception that says the "Task was canceled". 1.5 min correlates with about 4 tasks, if the Task.WhenAll awaits more than that it seems like that's when the exception is thrown.

This is what my code looks like:

The Api Call

private HttpClient _client = new HttpClient();

public async Task<DataObject> GetApiDataAsync(int id)
{
      return await _client.Get($"/entity/{id}");
}

The method that bundles the Api Calls

public async Task<IList<DataObject>> GetDataObjects(IList<int> ids)
{
     var requests = ids.Select(x => GetApiDataAsync(x));
     var responses = await Task.WhenAll(requests).ConfigureAwait(false);
     return responses.ToList();
}

The UI action that initiates

public async void ButtonClick()
{
     //First thing I tried 
     var data = await GetDataObjects(ids)

     //Second thing I tried
     var data = await Task.Run(() => GetDataObjects(ids));

    dataGridView = data;
}

I tried both methods above but both result in task cancelation if more than 1.5 mins passes (about 4 tasks).

Questions:

Which task is being canceled?

What is canceling the task?

Why is the task being canceled?

How can I successfuly run multiple http requests in parallel?

teaMonkeyFruit
  • 543
  • 4
  • 16
  • 2
    There are plenty of question explaining how to send multiple HTTP requests in parallel along with all problems one hit on the way... You probably already investigated those... but the code in the question has no traces of that investigation - please [edit] post provide that info. – Alexei Levenkov Apr 29 '20 at 06:19
  • 4
    Most likely your HTTP request is timing out (see [link](https://stackoverflow.com/a/29214208/2791540)), probably due to rate limiting, although it could be server overload or connection starvation as well. Don't think there is necessarily a code issue here. – John Wu Apr 29 '20 at 06:33
  • 1
    You probably need to [limit the amount of concurrent async I/O operations](https://stackoverflow.com/questions/10806951/how-to-limit-the-amount-of-concurrent-async-i-o-operations). 500 concurrent requests may be to many for the remote server to handle. – Theodor Zoulias Apr 29 '20 at 06:39
  • 1
    Why are you running your http calls using Task.Run? HttpClient has a default timeout of 100 seconds. A server that takes 50 seconds to respond is going to have a backlog of requests happening pretty quickly and your requests will timeout. – JohanP Apr 29 '20 at 09:46
  • I appreciate all the responses, I'm skeptical that it's an http time-out (the max server process time has been 60 seconds) but that's a great guess. I ended up moving the same code out to a web-api and it works as I'd expect without the task being canceled. In the web api I can drop in 10 `Task` into the `WhenAll()` and successfully complete all in about 70 sec. I keep getting the feeling it's something specific with the Winform applicaiton, e.g. the UI thread has more restrictions. – teaMonkeyFruit May 01 '20 at 18:51
  • @AlexeiLevenkov I followed the Stephan Cleary's best practices (which Ill add to an edit in the pose) example found here: https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-even-in.html and here: https://blog.stephencleary.com/2013/10/taskrun-etiquette-and-proper-usage.html – teaMonkeyFruit May 01 '20 at 18:52
  • @TheodorZoulias The dependent api is in a container sitting on google cloud run (kubernetes) with auto-scaling so, Im confident it can handle the 500 requests. – teaMonkeyFruit May 01 '20 at 18:52
  • @JohanP I was attempting to force the method to run on a background thread, as seen in Stephen Cleary's post linked above – teaMonkeyFruit May 01 '20 at 18:52

0 Answers0