簡體   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