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

时间:2014-07-28 21:05:50

标签: c# .net asynchronous async-await

如何将此同步方法调用链转换为异步(使用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;
}

3 个答案:

答案 0 :(得分:4)

要正确地执行异步,它是&#34; infectious&#34;,如果您在一个位置执行此操作,则需要在调用链中一直执行此操作以获得任何真正的好处。因此,无论是调用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关键字。 .ConfigureAwait(false)使得函数不必在UI线程上运行其余的代码,这可以为您带来小的性能提升。我不知道//do something with the myObject.中的代码是否要求你在UI线程上,所以我没有把它放在等待,但如果你不需要在UI线程上你也可以在那里添加它。

答案 1 :(得分:1)

你应该做DoRequest ......

Public async Task<HttpResponseMessage> DoRequest(...

然后返回await client.SendAsync

同样,DoSomething应该是异步任务&lt; ...&gt;

您的调用方法,如果您想将其称为fire并忘记,则Process可以是async void,否则为异步任务。

答案 2 :(得分:-1)

尝试:

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

await Task.WhenAll(task, task2);

如果您愿意,可以指定两个以上,或者只指定一个。