我正在实现一个定义异步方法的接口(interface) - 一个返回 Task<T>
的接口(interface)对象。
public class ValidationResult
{
// Properties that will hold the results of a validation.
}
public interface IValidator
{
Task<ValidationResult> Validate(object objectToValidate);
}
在大多数实现此接口(interface)的类中,Validate
中有异步工作要做。方法。因此,async
和 await
关键字被利用。
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
中,一些实现此接口(interface)的类没有异步工作要做方法。
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 警告。
This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
我从one particular question and answer了解到我可以简单地实现该方法而不包括 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
中会更好吗?对象使用 Task.FromException<ValidationResult>(ex)
?
最佳答案
If my synchronous code throws an Exception, should I let it fall through to the caller untouched? Or, would it be better to catch it and wrap it in a failed Task object using Task.FromException(ex)?
你应该把它放在返回的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);
}
}
或者,您可以使用不带 await
的 async
并使用 #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 { /* ... */ };
}
如果您经常这样做,您可以考虑创建一个辅助方法。 This one是 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 { /* ... */ };
});
}
关于c# - 解决警告 CS1998 : This async method lacks 'await' operators 时如何处理异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55542514/