【问题标题】:Writing new code in async but calling sync异步编写新代码但调用同步
【发布时间】:2016-03-04 14:27:24
【问题描述】:

我正在编写一些新代码,并希望使用 async 和 await 来编写它,但调用代码目前不是以 async 编写的。把新代码写成async,然后调用sync,直到调用代码支持async,对吗?

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

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

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

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

【问题讨论】:

  • 我强烈建议坚持“一直异步”的口头禅并立即更新代码。这是一个很好的阅读主题:blog.stephencleary.com/2012/07/dont-block-on-async-code.html 另外请记住,“我们稍后会修复其余部分”的方法很可能是整个软件开发行业中最普遍的错觉。不要半途而废。使代码异步或不异步。
  • 这就是所谓的“异步同步”,是一种反模式。这通常是一个非常糟糕的主意,并且同步异步或异步同步的某些组合可能完全死锁...

标签: c# .net asynchronous technical-debt


【解决方案1】:

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

然而,

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

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

这会被视为技术债吗?

根据定义,它是:

  1. 无论如何,您可能需要在未来进行同步调用,以支持这种情况,因此您已经承担了技术债务,您只是在处理它。

  2. 确实已经有技术债了。您说,“但调用代码当前不是异步编写的”。好了,那是你的债,已经在那里了。

  3. 如果同步和异步版本相互镜像(非常常见)并且您将方法放在它们的孪生方法旁边,则可以轻松地同时对每个方法进行大部分更改。

    李>

【讨论】:

    【解决方案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 就是技术债。

    【讨论】:

      【解决方案3】:

      根据 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 方法返回某些内容以便它移动到下一个参数。如果您要同步执行此操作,则执行将不得不等待并且总执行时间可能会更慢。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-16
        • 2014-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-26
        相关资源
        最近更新 更多