在异步中编写新代码但调用同步

时间:2016-03-04 14:27:25

标签: c# .net asynchronous technical-debt

我正在编写一些新代码,并希望使用async和await编写它,但调用代码当前不是用异步编写的。是否在异步中编写新代码并将其调用为同步,直到调用代码支持异步?

或者我应该编写代码同步,然后在以后转换它?它会被视为技术债务吗?

public Result Execute( Paramerters parameters ) {
    return ExecuteAsync( parameters ).Result;
}

public Task<Result> ExecuteAsync( Paramerters parameters ) {
    ...
}

Execute位于接口上,并从尚未异步的其他代码中调用。创建异步版本并从Execute调用它直到调用Execute的代码转换为异步是否正确? 我的旧代码是用.net 4.5.1编写的,但尚未转换为异步。

3 个答案:

答案 0 :(得分:3)

http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx对于为什么要避免这种情况有一些好处,以及如果不能解决问题,如何解决问题。

然而,

  

或者我应该编写代码同步,然后在以后转换它?

这可能更容易,而且完全摆脱了这个问题。

  

它会被视为技术债务吗?

根据定义,它是:

  1. 无论如何,您可能需要在未来很好地进行同步通话,以支持这种情况,因此您已经拥有了技术债务,而您只是处理它。

  2. 已经有了技术债务。你说,“但调用代码目前不是用异步编写的”。那里,那是你的债,已经存在。

  3. 如果同步和异步版本相互镜像(非常常见)并且您将方法放在他们的双胞胎旁边,则可以很容易地同时对每个方法进行大多数更改。

答案 1 :(得分:2)

我有一篇关于brownfield async development主题的MSDN文章 - 即将async引入同步代码库。有几种不同的方法,每种方法各有利弊。我的偏好是使用flag参数hack,如下:

public Result Execute(Parameters parameters)
{
  return ExecuteCoreAsync(parameters, sync: true).GetAwaiter().GetResult();
}

public Task<Result> ExecuteAsync(Parameters parameters)
{
  return ExecuteCoreAsync(parameters, sync: false);
}

private async Task<Result> ExecuteCoreAsync(Parameters parameters, bool sync)
{
  if (sync)
  {
    Thread.Sleep(2000); // sync implementation
    return new Result();
  }
  else
  {
    await Task.Delay(2000); // async implementation
    return new Result();
  }
}

是的,如果底层操作自然是异步的,那么同步API就是技术债务。

答案 2 :(得分:0)

根据ExecuteAsync的作用,它确实会产生显着的差异。

假设ExecuteAsync执行以下操作:

public Task<Result> ExecuteAsync( Paramerters parameters ) {
    List<Task> tasks = new List<Task>();
    foreach(var param in parameters)
    {
        var task = ExecuteSomethingElseAsync(param);
        tasks.Add(task);
    }
    Task.WhenAll(tasks.ToArray());
}

假设ExecutingSomethingelse是IO密集型的,其他任务将执行,而不必等待ExecuteSomething else方法返回一些东西,以便它移动到下一个param。如果您要同步执行此操作,则执行必须等待,并且总执行时间可能会更慢。

如果调用方法,则同步调用anyc方法可能包含一些好处,执行其他异步方法。