![](/img/trans.png)
[英]c# async await strange warning CS1998: This async method lacks 'await' operators
[英]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
方法中有異步工作要做。 因此,使用了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
方法中沒有異步工作要做。
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.