繁体   English   中英

解决警告 CS1998 时如何处理异常:此异步方法缺少“等待”运算符

[英]How do I handle Exceptions when resolving warning CS1998: This async method lacks 'await' operators

我正在实现一个定义异步方法的接口 - 一个返回Task<T>对象的接口。

public class ValidationResult
{
    // Properties that will hold the results of a validation.
}

public interface IValidator
{
    Task<ValidationResult> Validate(object objectToValidate);
}

在大多数实现此接口的类中,在Validate方法中有异步工作要做。 因此,使用了asyncawait关键字。

public class ExampleAsyncValidator : IValidator
{
    public override async Task<ValidationResult> Validate(object objectToValidate)
    {
        // Perform some asynchronous calls here which will use the await keyword.

        return new ValidationResult { /* ... */ };
    }
}

但是,某些实现此接口的类在Validate方法中没有异步工作要做

public class ExampleSyncValidator : IValidator
{
    public override async Task<ValidationResult> Validate(object objectToValidate)
    {
        // Perform only synchronous calls here. No use of the await keyword.

        return new ValidationResult { /* ... */ };
    }
}

如果async关键字用于上述同步场景中的Validate方法,那么我将收到来自编译器的 CS1998 警告。

此异步方法缺少“等待”运算符,并且将同步运行。 考虑使用 'await' 运算符来等待非阻塞 API 调用,或使用 'await Task.Run(...)' 在后台线程上执行 CPU 密集型工作。

我从一个特定的问题和答案中了解到,我可以简单地实现该方法,而无需包含async关键字并返回已完成的Task对象。

public class ExampleSyncValidator : IValidator
{
    public override Task<ValidationResult> Validate(object objectToValidate)
    {
        // Perform only synchronous calls here. No use of the await keyword.

        return Task.FromResult(new ValidationResult { /* ... */ });
    }
}

我的问题是:在这种情况下处理异常的最佳实践什么?

如果我的同步代码抛出一个异常,我应该让它原封不动地传递给调用者吗? 或者,使用Task.FromException<ValidationResult>(ex)捕获它并将其包装在失败的Task对象中会更好吗?

如果我的同步代码抛出一个异常,我应该让它原封不动地传递给调用者吗? 或者,使用 Task.FromException(ex) 捕获它并将其包装在失败的 Task 对象中会更好吗?

你应该把它放在返回的Task 即,使用Task.FromException

public override Task<ValidationResult> Validate(object objectToValidate)
{
  try
  {
    // Perform only synchronous calls here. No use of the await keyword.
    return Task.FromResult(new ValidationResult { /* ... */ });
  }
  catch (Exception ex)
  {
    return Task.FromException<ValidationResult>(ex);
  }
}

或者,您可以使用async而没有await并使用#pragma抑制警告:

#pragma warning disable 1998
public override async Task<ValidationResult> Validate(object objectToValidate)
#pragma warning restore 1998
{
  // Perform only synchronous calls here. No use of the await keyword.
  return new ValidationResult { /* ... */ };
}

如果你经常这样做,你可以考虑创建一个辅助方法。 是 Nito.AsyncEx 的一部分:

public static class TaskHelper
{
#pragma warning disable 1998
  public static async Task ExecuteAsTask(Action func)
#pragma warning restore 1998
  {
    func();
  }

#pragma warning disable 1998
  public static async Task<T> ExecuteAsTask<T>(Func<T> func)
#pragma warning restore 1998
  {
    return func();
  }
}

因此,如果您安装 Nito.AsyncEx 或在您的项目中包含上面的代码,那么您可以像这样使用ExecuteAsTask方法:

using static Nito.AsyncEx.TaskHelper;
...
public override Task<ValidationResult> Validate(object objectToValidate)
{
  return ExecuteAsTask(() => {
    // Perform only synchronous calls here. No use of the await keyword.
    return new ValidationResult { /* ... */ };
  });
}

正如其中一条评论指出的那样,编译器为您做了一些工作,以确保异步(使用 await 一词)方法的异常以异步方式出现,并且调试行为会进一步影响调用堆栈的保留方式。 如果方法契约返回一个任务,我的建议是让编译器为你完成这项工作......那就是

return await Task.FromResult(...)

否则,您可能会发现自己处于没有堆栈跟踪的断点处。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM