在c#中将一系列同步方法转换为异步方法

本文关键字:转换 异步方法 同步方法 一系列 | 更新日期: 2023-09-27 18:15:23

如何将这条同步方法调用链转换为async(使用async/await操作符)?假设只有最后一个调用DoRequest()需要花费时间来执行,那么它是唯一需要变为异步的方法吗?或者链中的所有调用者RequestSomething()和Process()也需要异步吗?

[HttpGet]
void Process()
{
   var url = "http://someapi.com";
   var myObject= RequestSomething(url);
   //do something with the myObject.
}    
MyObject RequestSomething(string url)
{
   var request = new HttpRequestMessage(HttpMethod.Get, url);
   var response = DoRequest(request);
   return JsonConvert.DeserializeObject<MyObject>(response);
}
//method that takes time to return.
HttpResponseMessage DoRequest(HttpRequestMessage request)
{
    var client = new HttpClient();
    return client.SendAsync(request).Result;
}

在c#中将一系列同步方法转换为异步方法

要正确地执行异步,它是"具有传染性的",如果你在一个位置执行异步,你需要在调用链的所有位置执行异步,才能从中获得真正的好处。因此,无论调用Process()的是什么,都需要处理从Process返回的任务,要么等待它,要么像DoRequest那样将它传递到链上。

async Task Process()
{
   var url = "http://someapi.com";
   var myObject= await RequestSomething(url);
   //do something with the myObject.
}    
async Task<MyObject> RequestSomething(string url)
{
   var request = new HttpRequestMessage(HttpMethod.Get, url);
   var response = await DoRequest(request).ConfigureAwait(false);
   return JsonConvert.DeserializeObject<MyObject>(response);
}
//method that takes time to return.
Task<HttpResponseMessage> DoRequest(HttpRequestMessage request)
{
    var client = new HttpClient();
    return client.SendAsync(request);
}

因为在执行请求后不做任何额外的工作,所以在DoRequest函数中不需要async/await,但其他函数将需要async/await关键字。.ConfigureAwait(false)使得函数不必在UI线程上运行它的其余代码,这可以给你一个小小的性能提升。我不知道//do something with the myObject.中的代码是否需要你在UI线程上,所以我没有把它放在那个等待上,但是如果你不需要在UI线程上,你也可以把它添加到那里。

你应该让DoRequest…

Public async Task<HttpResponseMessage> DoRequest(...

然后返回等待客户端。

是以

同样,DoSomething应该是async Task<…>

你的调用方法,Process可以是async void,如果你想调用它作为fire and forget,否则是一个async Task。

尝试:

var task = Task.Run(() => RequestSomething());
var task2 = Task.Run(() => RequestSomethingElse());
await Task.WhenAll(task, task2);

可以指定两个以上,也可以只指定一个。