共用方式為


使用 await 運算子解決非同步方法中的錯誤和警告

本文涵蓋下列編譯器錯誤:

  • CS1983由於這是非同步方法,因此傳回運算式必須是 'Task<T>' 類型,而不是 'T'。
  • CS1985無法在 catch 子句中等候。
  • CS1986'await' 要求類型具有適當的 'GetAwaiter' 方法。
  • CS1989非同步 Lambda 運算式無法轉換成運算式樹狀結構。
  • CS1991'Type' 無法實作 'event',因為它是 Windows 執行階段事件,而 'event' 是一般 .NET 事件。
  • CS1992只有在包含以 'async' 修飾詞標示的方法或 lambda 運算式中時,才能使用 'await' 運算子。
  • CS1994'async' 修飾詞只能用於具有方法主體的方法。
  • CS1995'await' 運算子只能用於初始 'from' 子句的第一個集合運算式內的查詢運算式,或 'join' 子句的集合運算式內。
  • CS1996無法在 lock 語句的區塊中等待。
  • CS1997由於函式是傳回值的非同步方法,因此 return 關鍵字後面不得接著物件運算式。
  • CS1998此非同步方法缺少 'await' 運算子,而且會同步執行。請考慮使用 'await' 運算子來等待非阻塞 API 呼叫,或使用 'await Task.Run(...)' 在背景執行緒上執行 CPU 繫結的工作。
  • CS4008無法等候 'void'。
  • CS4009void 或 int 傳回進入點不能是非同步的。
  • CS4014因為不會等候此呼叫,所以在呼叫完成之前,目前方法會繼續執行。請考慮將運算 await 子套用至呼叫的結果。
  • CS4032'await' 運算子只能在非同步方法內使用。請考慮使用 'async' 修飾符標記此方法,並將其傳回類型變更為 'Task<T>'。
  • CS4033'await' 運算子只能在非同步方法內使用。考慮使用 'async' 修飾符標記此方法並將其傳回類型變更為 'Task'。
  • CS8892方法不會用作進入點,因為找到同步進入點。
  • CS9123不應該在非同步方法中的參數或區域變數上使用 '&' 運算子。
  • CS9330'MethodImplAttribute.Async' 無法手動套用至方法。將方法標示為「非同步」。

等待運算式條件

  • CS1985無法在 catch 子句中等候。
  • CS1986'await' 要求類型具有適當的 'GetAwaiter' 方法。
  • CS1992只有在包含以 'await' 修飾詞標示的方法或 Lambda 運算式中時,才能使用 'async' 運算子。
  • CS1995'await' 運算子只能用於初始 'from' 子句的第一個集合運算式內的查詢運算式,或 'join' 子句的集合運算式內。
  • CS1996無法在鎖定陳述式的內文中等候。
  • CS4008無法等候 'void'。
  • CS4032'await' 運算子只能在非同步方法內使用。考慮使用 'async' 修飾符標記此方法並將其傳回類型變更為 'Task<T>'。
  • CS4033'await' 運算子只能在非同步方法內使用。考慮使用 'async' 修飾符標記此方法並將其傳回類型變更為 'Task'。

若要正確使用 await 運算子,請遵循下列規則。 如需詳細資訊,請參閱 使用非同步程式設計:async 和 await

  • 請勿在 catch 子句中使用 awaitCS1985)。 雖然您可以在 C# 6 和更高版本的 try 區塊和 finally 區塊中使用 await,但 catch 區塊在例外處理和控制流程方面會帶來特殊挑戰。
  • 請勿在lock陳述式區塊內使用awaitCS1996)。 編譯器不支援此功能,以避免發出容易發生死結的程式碼。
  • await僅在查詢運算式CS1995) 內的特定位置使用:在初始from子句的第一個集合運算式內,或在子句的join集合運算式內。
  • 在使用 await 之前,請使用 async 修飾詞將方法或 lambda 運算式標記(CS1992CS4032CS4033)。
  • 請確定等候的類型具有傳回等候者類型的可存取 GetAwaiter 方法 (CS1986) 。
  • 不適用於 await 類型 voidCS4008) 的運算式。
  • 將傳回類型變更為 Task 不傳回值的方法,或 Task<T> 傳回值的方法。

非同步方法簽名需求

  • CS1983由於這是非同步方法,因此傳回運算式必須是 'Task<T>' 類型,而不是 'T'。
  • CS1994'async' 修飾詞僅適用於具有主體的方法。
  • CS4009返回類型為 void 或 int 的入口點無法是非同步的。
  • CS8892方法不會用作進入點,因為找到同步進入點。
  • CS9330'MethodImplAttribute.Async' 無法手動套用至方法。標記方法「async」。

若要正確宣告非同步方法,請遵循下列簽章需求。 如需詳細資訊,請參閱 非同步主要傳回值

  • 傳回其中一個有效類型: voidTaskTask<T>、類似工作的類型、 IAsyncEnumerable<T>IAsyncEnumerator<T>CS1983)。
  • 僅在具有本文的方法上使用 async 修飾詞 (CS1994)。 移除 async 介面或類別中抽象方法上的修飾符。
  • 請將版本更新至 C# 7.1 或更高版本,以在進入點Main上使用async,或避免在早期版本(CS4009)的進入點上使用async
  • 如果您同時具有同步和非同步進入點,請移除同步進入點 (CS8892)。
  • 使用 async 關鍵字,而不是手動套用 MethodImplAttribute.AsyncCS9330)。

非同步做法

  • CS1989非同步 Lambda 運算式無法轉換成運算式樹狀結構。
  • CS1991'Type' 無法實作 'event',因為它是 Windows 執行階段事件,而 'event' 是一般 .NET 事件。
  • CS1997由於函式是傳回值的非同步方法,因此 return 關鍵字後面不得接著物件運算式。
  • CS1998此非同步方法缺少 'await' 運算子,而且會同步執行。請考慮使用 'await' 運算子來等待非阻塞 API 呼叫,或使用 'await Task.Run(...)' 在背景執行緒上執行 CPU 繫結的工作。
  • CS4014因為不會等候此呼叫,所以在呼叫完成之前,目前方法會繼續執行。請考慮將運算 await 子套用至呼叫的結果。
  • CS9123不應該在非同步方法中的參數或區域變數上使用 '&' 運算子。

若要正確撰寫非同步程式碼並避免常見陷阱,請遵循以下最佳實踐。 如需詳細資訊,請參閱 使用非同步程式設計:async 和 await

  • 一律等待 傳回TaskTask<TResult>的非同步方法呼叫(CS4014)。 未處理的呼叫可能會導致例外丟失和意外的行為。
  • 請勿從傳回 Task (非泛型) 的非同步方法傳回值;請改用 Task<T>CS1997)。
  • 在非同步方法中包含至少一個 await 運算子,或移除 async 修飾詞 (CS1998)。
  • 如果方法應該傳回 returnTaskCS1998) ,請移除陳述式。
  • 將方法的傳回類型變更為 Task<T> 以傳回值 (CS1997CS1998) 。
  • 如果您不需要非同步狀態機,請移除 async 修飾詞並直接傳回工作 (CS1997CS1998)。
  • 請勿在運算式樹狀結構中使用非同步方法 (CS1989)。 運算式樹狀結構會將程式碼表示為資料,而且不支援非同步方法所需的複雜狀態機器轉換。
  • 切勿將介面或 WinRT 事件中的加入或移除的存取子標記為非同步(CS1991)。 這是 Windows 執行階段互通性的平臺特定限制。
  • 避免在非同步方法內的運算式上使用 address-of 運算子 (&) (CS9123)。 在暫停期間,目標可能會重新定位在記憶體中,使指標無效。