The following method loops through a list of postdata to make multiple requests for a token, for example each request uses a specific clientID. My question relates to async. I'm trying to make the calls for the token(s) to be async. Does the use of .Result necessarily make the method synchronous?
public async Task<string> ReturnDataFromUrl1(List<List<KeyValuePair<string, string>>> listOfPostData)
{
List<Task<string>> taskList = new List<Task<string>>();
string allTokens = "";
List<Task<string>> downloadTasks = new List<Task<string>>();
foreach (var postData in listOfPostData)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:23081");
HttpContent httpContent = new FormUrlEncodedContent(postData);
HttpResponseMessage response = client.PostAsync("/Token", httpContent).Result;
var responsecode = (int)response.StatusCode;
if (response.IsSuccessStatusCode)
{
var responseBodyAsText = response.Content.ReadAsStringAsync();
taskList.Add(responseBodyAsText);
}
}
}
downloadTasks = taskList.ToList();
while (downloadTasks.Count > 0)
{
Task<string> firstFinishedTask = await Task.WhenAny(downloadTasks);
downloadTasks.Remove(firstFinishedTask);
// Await the completed task.
string content = await firstFinishedTask;
allTokens = allTokens + content;
}
return allTokens;
}
It will make the part which blocks with
.Result
synchronous, as it synchronously waits for the completion of theTask
(If your code doesn't deadlocking, which is highly possible in an environment with a customSynchronizationContext
).This method invocation:
Will be asynchronous as it will yield control until the first stream is read and converted to a string. If you already have a method marked as
async
, simplyawait
that part as well:Side Note:
I think I would of taken a different approach to the problem. Generally, it's the network IO which will consume the most time for this method. If possible and given no limitation, I'd concurrently make those network calls, and then process the results as they come:
Or since you need all of the results in order to process the the token anyway, you can use
Task.WhenAll
to wait on all of them to complete: