【问题标题】:Best way to handle null task inside async method? [closed]在异步方法中处理空任务的最佳方法? [关闭]
【发布时间】:2014-12-19 01:13:13
【问题描述】:

async 方法中处理null 任务的最佳方法是什么?

public class MyClass
{
   private readonly Task task;
   public MyClass(Task task) { this.task = task; }

   public async Task Execute()
   {
      if (task == null)
      {
         await Task.Yield(); /* Is this the best way? */
         return;
      }
      await task;
   }
}

【问题讨论】:

  • 你想做什么?
  • 我会说public MyClass(Task task){if (task == null)throw new ArgumentNullException("task");..}
  • 只是不要接受空任务。顺便说一句,你想做什么?包装一个任务并添加一个执行方法是非常可疑的,并且可能是代码异味 - 试图“控制”任务何时开始或执行,而没有理由这样做。 Task 本身一个在其委托启动和执行时进行抽象的类,您无需在其之上添加另一个类来做同样的事情。
  • 我试图了解在异步方法中处理可能为空的任务的最佳实践。出于讨论的目的,假设我继承了一个可能允许空任务的方法,并且在构造函数中添加空检查不是一种选择。

标签: c# .net task-parallel-library async-await


【解决方案1】:

您不需要处理null 任务。只需对它进行空检查:

public async Task Execute()
{
   if (task != null)
   {
       await task;
   }
}

或者更好的是,只需返回任务,因为您在 await 之后没有添加任何内容:

public Task Execute()
{
   return task;
}

如果你想返回一个已完成的任务而不是null,你可以使用Task.FromResult

public Task Execute()
{
   return task ?? Task.FromResult(false);
}

【讨论】:

  • "Task.FromResult(false)" 当您有一个无法严格抽象的可覆盖方法时效果很好。感谢您的出色回答。
  • 现在 Elvis 运算符非常常见 (.?) -- 我有一个扩展方法使用这种方法来确保那些等待调用总是有效:public static Task<T> NullSafe<T>(this Task<T> task) => task ?? Task.FromResult(default(T)); -- 所以你可以写var x = await (someObject?.DoTheThing()).NullSafe(); 之类的代码(请记住,由于 Elvis 运算符的工作方式,括号在此语句中很重要。)
  • “Task.CompletedTask”也是一个选项
【解决方案2】:

如果任务从不为空,则大多数异步代码会更干净。使用Task.FromResult(0) 或类似的构造来代替空任务。

public class MyClass
{
  private readonly Task task;
  public MyClass(Task task) { this.task = task ?? Task.FromResult(0); }

  public async Task ExecuteAsync()
  {
    await task;
  }
}

或者,如果这就是你的 ExecuteAsync 所做的一切:

public Task ExecuteAsync()
{
  return task;
}

请注意,当调用构造函数时,任务已经在运行,这使得方法名称ExecuteAsync 用词不当。如果您希望任务在调用ExecuteAsync开始,那么您真正想要存储的是Func<Task>

public class MyClass
{
  private readonly Func<Task> func;
  public MyClass(Func<Task> func) { this.func = func ?? () => Task.FromResult(0); }

  public async Task ExecuteAsync()
  {
    await func();
  }
}

【讨论】:

    【解决方案3】:

    在异步方法中处理空任务的最佳方法是什么?

    最佳实践通常包括不允许空参数(除非业务规则要求)。

    public class MyClass
    {
       private readonly Task _task;
    
       public MyClass(Task task) 
       { 
         if (task == null)
         {
           throw new ArgumentNullException("task");
         }
    
         this._task = task; 
       }
    
       public async Task Execute()
       {
          await this._task;
       }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      • 1970-01-01
      • 2019-08-04
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      • 1970-01-01
      相关资源
      最近更新 更多