这种方法是异步的吗?

时间:2015-11-28 22:40:13

标签: c# asynchronous task httpclient response

此方法使用.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;
}

1 个答案:

答案 0 :(得分:2)

所以目前这个电话:

HttpResponseMessage response = client.PostAsync("/Token", content).Result;

将导致调用线程停止并等待结果。如果在client.PostAsync之前放置await关键字,它将导致调用线程返回调用者并在操作完成后恢复。由于这是在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,请注意你的名字)

我们可以再次在response.Content之前放置await关键字,并自动推断返回键。然后我们可以在linq查询中选择字符串,而不是Task<string>

相关问题