本文涵蓋下列編譯器錯誤:
-
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'。 - CS4009: void 或 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 子句中使用
await(CS1985)。 雖然您可以在 C# 6 和更高版本的 try 區塊和 finally 區塊中使用await,但 catch 區塊在例外處理和控制流程方面會帶來特殊挑戰。 - 請勿在
lock陳述式區塊內使用await(CS1996)。 編譯器不支援此功能,以避免發出容易發生死結的程式碼。 -
await僅在查詢運算式 (CS1995) 內的特定位置使用:在初始from子句的第一個集合運算式內,或在子句的join集合運算式內。 - 在使用
await之前,請使用async修飾詞將方法或 lambda 運算式標記(CS1992、CS4032、CS4033)。 - 請確定等候的類型具有傳回等候者類型的可存取
GetAwaiter方法 (CS1986) 。 - 不適用於
await類型void(CS4008) 的運算式。 - 將傳回類型變更為
Task不傳回值的方法,或Task<T>傳回值的方法。
非同步方法簽名需求
-
CS1983: 由於這是非同步方法,因此傳回運算式必須是 '
Task<T>' 類型,而不是 'T'。 -
CS1994: '
async' 修飾詞僅適用於具有主體的方法。 - CS4009:返回類型為 void 或 int 的入口點無法是非同步的。
- CS8892: 方法不會用作進入點,因為找到同步進入點。
-
CS9330: '
MethodImplAttribute.Async' 無法手動套用至方法。標記方法「async」。
若要正確宣告非同步方法,請遵循下列簽章需求。 如需詳細資訊,請參閱 非同步主要傳回值。
- 傳回其中一個有效類型:
void、 Task、Task<T>、類似工作的類型、 IAsyncEnumerable<T>或 IAsyncEnumerator<T> (CS1983)。 - 僅在具有本文的方法上使用
async修飾詞 (CS1994)。 移除async介面或類別中抽象方法上的修飾符。 - 請將版本更新至 C# 7.1 或更高版本,以在進入點
Main上使用async,或避免在早期版本(CS4009)的進入點上使用async。 - 如果您同時具有同步和非同步進入點,請移除同步進入點 (CS8892)。
- 使用
async關鍵字,而不是手動套用MethodImplAttribute.Async(CS9330)。
非同步做法
- CS1989: 非同步 Lambda 運算式無法轉換成運算式樹狀結構。
- CS1991: 'Type' 無法實作 'event',因為它是 Windows 執行階段事件,而 'event' 是一般 .NET 事件。
- CS1997: 由於函式是傳回值的非同步方法,因此 return 關鍵字後面不得接著物件運算式。
-
CS1998: 此非同步方法缺少 '
await' 運算子,而且會同步執行。請考慮使用 'await' 運算子來等待非阻塞 API 呼叫,或使用 'await Task.Run(...)' 在背景執行緒上執行 CPU 繫結的工作。 -
CS4014: 因為不會等候此呼叫,所以在呼叫完成之前,目前方法會繼續執行。請考慮將運算
await子套用至呼叫的結果。 -
CS9123: 不應該在非同步方法中的參數或區域變數上使用 '
&' 運算子。
若要正確撰寫非同步程式碼並避免常見陷阱,請遵循以下最佳實踐。 如需詳細資訊,請參閱 使用非同步程式設計:async 和 await。
- 一律等待 傳回Task或Task<TResult>的非同步方法呼叫(CS4014)。 未處理的呼叫可能會導致例外丟失和意外的行為。
- 請勿從傳回
Task(非泛型) 的非同步方法傳回值;請改用Task<T>(CS1997)。 - 在非同步方法中包含至少一個
await運算子,或移除async修飾詞 (CS1998)。 - 如果方法應該傳回
return(Task、CS1998) ,請移除陳述式。 - 將方法的傳回類型變更為
Task<T>以傳回值 (CS1997、 CS1998) 。 - 如果您不需要非同步狀態機,請移除
async修飾詞並直接傳回工作 (CS1997、 CS1998)。 - 請勿在運算式樹狀結構中使用非同步方法 (CS1989)。 運算式樹狀結構會將程式碼表示為資料,而且不支援非同步方法所需的複雜狀態機器轉換。
- 切勿將介面或 WinRT 事件中的加入或移除的存取子標記為非同步(CS1991)。 這是 Windows 執行階段互通性的平臺特定限制。
- 避免在非同步方法內的運算式上使用 address-of 運算子 (
&) (CS9123)。 在暫停期間,目標可能會重新定位在記憶體中,使指標無效。