在异步模式下编写新代码但调用同步模式

3

我正在编写一些新的代码,并希望使用async和await来编写。但是调用该代码的现有代码并不支持async。在现有代码支持async之前,将新代码编写为async然后同步调用是否正确?

还是应该先编写同步代码,然后稍后转换代码?这是否被认为是技术债务?

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

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

Execute 是一个接口上的方法,被一些尚未异步化的代码调用。在将调用 Execute 的代码异步化之前,创建异步版本并从 Execute 调用它是正确的吗? 我的旧代码是使用 .net 4.5.1 编写的,但尚未转换为异步。


4
我强烈建议坚持“异步自始至终”的口号并立即更新代码。这篇文章对此很好地阐述了:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html。同时要记住,“我们之后会修复剩下的部分”的做法很可能是整个软件开发行业中最普遍的错觉。不要半途而废,要么使代码异步,要么不要。 - David
5
这被称为“同步超异步”,是一种反模式。这通常是一个非常糟糕的想法,某些同步超异步或异步超同步的组合可能会完全死锁... - Marc Gravell
3个回答

3
http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx 中提到了避免使用同步调用的原因以及如果无法避免该问题,应该如何缓解。
然而,
引用如下:
“我应该写同步代码,然后在以后将其转换吗?”
这样做可能更容易,并且完全避免了这个问题。
引用如下:
“这是否会被视为技术债务?”
根据定义是技术债务,尽管:
1.您可能仍需要长期进行同步调用,以支持该情况,因此您已经有了这种技术债务,只是在处理它。
2.您已经拥有了这种技术债务。您说:“但是调用代码当前未以异步方式编写。” 这就是你的债务,已经存在。
3.如果同步和异步版本相互映射(非常常见),并且您将方法放置在它们的对应位置,那么大多数更改可以同时进行。

2
我有一篇关于“棕地(传统)async开发”的MSDN文章,即在同步代码库中引入async。有几种不同的方法,每种方法都有其优缺点。我的偏好是使用标志参数黑客技巧,如下所示:
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就是技术债务。


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());
}

假设执行“执行其他事情”是IO密集型的,那么其他任务将执行而无需等待ExecuteSomethingElse方法返回结果才能继续执行下一个参数。如果同步执行,则execute将必须等待,总执行时间可能会更慢。
如果被调用的方法执行其他异步方法,则同步调用任何方法可能会有一些好处。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接