用同步版本替换异步方法 - 缺点?

时间:2016-01-14 09:38:56

标签: c# .net http methods async-await

我的应用程序有一个异步方法,它简化了我的需求的HTTP请求:

public async Task<string> MyAsyncMethod()
{
  ...

  using (var httpResp = (HttpWebResponse)await req.GetResponseAsync().ConfigureAwait(false))
  {
    ...

    using (StreamReader reader = new StreamReader(
      httpResp.GetResponseStream()))
    {
      return _response = await reader.ReadToEndAsync().ConfigureAwait(false);
    }
  }
}

现在我想通过重用尽可能多的代码来制作相应的非异步方法。

我正在考虑做以下事情:

  • 重写方法同步方法(使用GetResponse和ReadToEnd而不是异步方法)
  • 使用引用同步方法的方法替换ResponseAsync()

但是这意味着我可以完全抛弃我的异步方法并始终在异步上下文中使用我的sync方法,这会减少异步嵌套(这很好)。我的意思是在两种情况下,无论如何都在异步上下文中完成相同的操作(例如获得响应),那么有什么区别?

2 个答案:

答案 0 :(得分:3)

  

但这意味着我可以完全放弃我的异步方法并始终使用   异步上下文中的同步方法,可以减少异步嵌套   (这很好)。我的意思是在两种情况下都是相同的操作(例如获得   响应)无论如何都是在异步上下文中完成的

那是不对的。如果通过&#34;在异步上下文中使用我的同步方法&#34; ,则表示使用Task.Run(即async over sync anti-pattern)包装同步版本,那么这不是与使用真正的异步方法相同。当您使用异步方法时,在异步操作正在进行时,您将释放调用线程以执行更多工作。当您使用同步版本时,您正在执行相反的操作,直到该方法调用完成后,您才会阻止。当您使用Task.Run包装阻止方法时,您&# 39;实际上使用另一个线程只是为了阻止它,因为代理将是你的同步版本。

旁注: 使用HttpClient可以大大减少卸载请求所需的代码量:

public Task<string> RequestAsync(string url)
{
    var httpClient = new HttpClient();
    return httpClient.GetAsStringAsync(url);
}

答案 1 :(得分:0)

不同之处在于返回async的{​​{1}}方法将立即返回(即,除非您明确指定Task,否则不会等待操作完成)。

因此,对于您的情况,您的方法不会发生很大变化,但您的方法的用法可能会有所不同,因为您不需要事件来告诉您执行已完成;代码在完成后继续。