这个方法是异步的吗
本文关键字:异步 方法 | 更新日期: 2023-09-27 18:24:50
此方法使用.Result
。这是否意味着任务不会异步运行?是否需要重构才能使每个对令牌的请求真正异步?
public async Task<string> ReturnDataFromUrlAsync(List<List<KeyValuePair<string, string>>> listOfPostData)
{
string allTokens = "";
var client = new HttpClient
{
BaseAddress = new Uri("http://localhost:23081")
};
var downloadTasksQuery = listOfPostData.Select(postData =>
{
var content = new FormUrlEncodedContent(postData);
HttpResponseMessage response = client.PostAsync("/Token", content).Result;
var responseBodyAsText = response.Content.ReadAsStringAsync();
return responseBodyAsText;
});
List<Task<string>> downloadTasks = downloadTasksQuery.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;
}
所以现在这个调用:
HttpResponseMessage response = client.PostAsync("/Token", content).Result;
将导致调用线程暂停并等待结果。如果将wait关键字放在client.PostAsync
之前,它将导致调用线程返回到调用者,并在操作完成后继续。由于这是在linq查询中完成的,您需要使lambda表达式异步,如下所示:
var downloadTasksQuery = listOfPostData.Select(async postData =>
{
var content = new FormUrlEncodedContent(postData);
HttpResponseMessage response = await client.PostAsync("/Token", content);
var responseBodyAsText = await response.Content.ReadAsStringAsync();
return responseBodyAsText;
});
在lambda表达式中追加async关键字将推断返回类型必须为Task类型,并且由于我们也在选择字符串,因此返回类型将为IEnumerable<Task<string>>
我还注意到:
var responseBodyAsText = response.Content.ReadAsStringAsync();
我认为造成混乱的原因是,这条语句实际上返回的是Task,而不是字符串(如果使用var
,请小心命名)
再次,我们可以将wait关键字放在response.Content
之前,返回关键字将自动推断出来。然后我们可以在linq查询中选择字符串,而不是Task<string>