逐步解說:搭配非同步方法使用偵錯工具
您可以使用非同步功能,您可以呼叫非同步方法,而不需使用回呼或分割您的多個方法或 Lambda 運算式的程式碼。 若要使程式碼非同步,您呼叫非同步方法而非使用同步方法並加入一些關鍵字加入程式碼。 如需詳細資訊,請參閱使用 Async 和 Await 設計非同步程式 (C# 和 Visual Basic)。
在 Visual Studio 偵錯工具,您可以使用 [逐步執行]、 [步驟] 和 [步驟] 命令與 Async 功能。 您也可以繼續使用中斷點,特別是檢視包含 Await 運算子的陳述式的控制流程。 在這個逐步解說中,您將完成下列工作,您可以依任何順序執行。
示範在等候陳述式的控制流程使用中斷點。
了解 [逐步執行] 和 [步驟] 命令的行為在包含 Await 運算子的陳述式。
因此,使用它從非同步方法的內部時,所發生的 [步驟] 命令的行為。
顯示控制流程的中斷點
如果您將標記為已使用 Async (Visual Basic) 或 (C#) 非同步 修飾詞的方法,在方法中使用 等候 (Visual Basic) 或 等候 (C#) 運算子。 若要建立等候運算式,您使 Await 運算子與工作。 當等候運算式工作時,會呼叫目前的方法會立即完成並傳回不同的工作。 當與 Await 運算子時的工作完成,執行在相同方法繼續。 如需詳細資訊,請參閱非同步程式中的控制流程 (C# 和 Visual Basic)。
注意事項 |
---|
非同步方法傳回給呼叫端時,可能會遇到不完整時或是在非同步方法的結尾先等候的物件,最先出現。 |
注意事項 |
---|
在這些範例中的主控台應用程式使用 Wait 方法可防止應用程式終止的 Main。因為死結情況可能發生,您不應該使用 Wait 方法在主控台應用程式外。 |
示範發生了什麼的下列程序中設定中斷點,當應用程式執行等候陳述式。 您也可以將示範控制流程將 Debug.WriteLine 陳述式。
建立主控台應用程式,然後將下列程式碼貼入其中:
' Breakpoints to show control flow. Imports System.Threading.Tasks Module Module1 Sub Main() Dim theTask = ProcessAsync() Dim x = 0 ' set breakpoint theTask.Wait() End Sub Async Function ProcessAsync() As Task Dim result = Await DoSomethingAsync() ' set breakpoint Dim y = 0 ' set breakpoint End Function Async Function DoSomethingAsync() As Task(Of Integer) Await Task.Delay(1000) Return 5 End Function End Module
// Breakpoints to show control flow. using System.Threading.Tasks; class Program { static void Main(string[] args) { Task theTask = ProcessAsync(); int x = 0; // set breakpoint theTask.Wait(); } static async Task ProcessAsync() { var result = await DoSomethingAsync(); // set breakpoint int y = 0; // set breakpoint } static async Task<int> DoSomethingAsync() { await Task.Delay(1000); return 5; } }
設定以「設定中斷點」註解結束三行的偵錯中斷點。
選擇 F5 鍵或選取 [偵錯],請在功能表列上的 [啟動偵錯] 執行應用程式。
應用程式在包含 Await 運算子的行進入 ProcessAsync 方法而中斷。
再次選擇 F5 鍵。
由於應用程式中包含 Await 運算子的陳述式停止,應用程式會立即結束非同步方法並傳回工作。 因此,應用程式就會結束 ProcessAsync 方法而中斷。在呼叫的方法 (Main) 的中斷點。
再次選擇 F5 鍵。
在 DoSomethingAsync 方法完成時,程式碼會在呼叫方法的等候陳述式之後繼續。 因此,應用程式中斷在 ProcessAsync 方法中的中斷點。
當 DoSomethingAsync 最初等候, ProcessAsync 方法會結束並傳回工作。 當等候的 DoSomethingAsync 方法會完成,等候陳述式的評估產生傳回值 DoSomethingAsync。 DoSomethingAsync 方法在 C# 中定義傳回在 Visual Basic 中的 Task (Of Integer) 或 Task<int> ,因此,在其傳回陳述式的值是整數。 如需詳細資訊,請參閱非同步方法的傳回型別 (C# and Visual Basic)。
取得然後等候工作
在 ProcessAsync 方法中,陳述式 Dim result = Await DoSomethingAsync() (Visual Basic) 或 var result = await DoSomethingAsync(); (C#) 為下列兩個陳述式的縮小:
Dim theTask = DoSomethingAsync()
Dim result = Await theTask
var theTask = DoSomethingAsync();
var result = await theTask;
第一個程式碼會呼叫非同步方法並傳回工作。 該工作與下一行程式碼的 Await 運算子。 等候陳述式結束方法 (ProcessAsync) 和傳回不同的工作。 當與 Await 運算子時的工作完成時,程式碼在方法 (ProcessAsync) 繼續等候陳述式之後。
當等候陳述式立即傳回不同的工作時,該工作是包含 Await 運算子的非同步方法傳回的引數 (ProcessAsync)。 由等候傳回這些工作時,會發生在相同方法之後的等候,是的程式碼執行該工作為何與等候的工作不同。
逐步執行並逐步執行
[逐步執行] 命令逐步執行方法,不過, [步驟] 命令會呼叫方法的下一行執行方法呼叫然後中斷。 如需詳細資訊,請參閱[NIB] 程式碼逐步執行概觀。
下列程序顯示出現,當您選取 [逐步執行] 或 [步驟] 命令在等候陳述式。
以下列程式碼取代在主控台應用程式的程式碼。
' Step Into and Step Over Example Imports System.Threading.Tasks Module Module1 Sub Main() ProcessAsync.Wait() End Sub Async Function ProcessAsync() As Task Dim result = Await DoSomethingAsync() ' Step Into or Step Over from here Dim y = 0 End Function Async Function DoSomethingAsync() As Task(Of Integer) Await Task.Delay(1000) Return 5 End Function End Module
// Step Into and Step Over Example. using System.Threading.Tasks; class Program { static void Main(string[] args) { ProcessAsync().Wait(); } static async Task ProcessAsync() { var result = await DoSomethingAsync(); // Step Into or Step Over from here int y = 0; } static async Task<int> DoSomethingAsync() { await Task.Delay(1000); return 5; } }
選擇 F11 鍵或選取 [偵錯],請在功能表列上的 [逐步執行] 開始 Step Into 命令的示範含有 Await 運算子的陳述式。
應用程式在第一行開始並中斷,是在 Visual Basic 或 Main 方法左大括號的 C# 中的 Sub Main() 。
選擇 F11 鍵三倍。
應用程式應該會在 ProcessAsync 方法的等候陳述式。
選擇 F11 鍵。
應用程式在第一行輸入 DoSomethingAsync 方法而中斷。 這種行為的發生,即使,而在 await 陳述式中,應用程式會立即回到呼叫的方法 (Main)。
選取到應用程式的 Keep F11 鍵回 ProcessAsync 方法等候的陳述式。
選擇 F11 鍵。
應用程式必須在等候陳述式的分行符號。
在功能表列上,選擇 [偵錯]],則 [停止偵錯] 停止執行。
下列步驟示範 [步驟] 命令在等候陳述式。
選擇 F11 鍵四次或選取 [偵錯],請在功能表列上的 [逐步執行] 四次。
應用程式應該會在 ProcessAsync 方法的等候陳述式。
選擇 F10 鍵或選取 [偵錯],請在功能表列上的 [步驟] 。
執行中斷之後等候陳述式的行。 這種行為的發生,即使應用程式立即傳回給呼叫的方法 (Main) 在等候陳述式。 Step Over 命令也不進入 DoSomethingAsync 方法的執行,如預期般運作。
在功能表列上,選擇 [偵錯]],則 [停止偵錯] 停止執行。
在下列步驟中,會顯示 [逐步執行] 和 [步驟] 命令的行為稍有不同,因為 Await 運算子是在從呼叫中不同的行至非同步方法時。
在 ProcessAsync 方法中,以下列程式碼取代等候陳述式。 原始等候陳述式是下列兩個陳述式的合約。
Dim theTask = DoSomethingAsync() Dim result = Await theTask
var theTask = DoSomethingAsync(); var result = await theTask;
選擇 F11 鍵或選取 [偵錯],請在功能表列上多次的 [逐步執行] 至程式碼開始執行和步驟。
在對 DoSomethingAsync的呼叫, [ [逐步執行] 命令在 DoSomethingAsync 方法中),,而 [步驟] 命令移至下一個陳述式,如預期般運作。 在等候陳述式,兩個命令中斷之後等候的陳述式。
跳離函式
在不是的非同步方法, [步驟] 命令會在之後呼叫方法的程式碼呼叫的方法中斷。 如需非同步方法,執行在呼叫的方法中斷的邏輯較為複雜和該邏輯取決於 [步驟] 命令是否在非同步方法的第一行。
以下列程式碼取代在主控台應用程式的程式碼。
' Step Out Example Imports System.Threading.Tasks Module Module1 Sub Main() ProcessAsync.Wait() End Sub Async Function ProcessAsync() As Task Dim theTask = DoSomethingAsync() Dim z = 0 Dim result = Await theTask End Function Async Function DoSomethingAsync() As Task(Of Integer) Debug.WriteLine("before") ' Step Out from here Await Task.Delay(1000) Debug.WriteLine("after") Return 5 End Function End Module
// Step Out Example. using System.Diagnostics; using System.Threading.Tasks; class Program { static void Main(string[] args) { ProcessAsync().Wait(); } static async Task ProcessAsync() { var theTask = DoSomethingAsync(); int z = 0; var result = await theTask; } static async Task<int> DoSomethingAsync() { Debug.WriteLine("before"); // Step Out from here await Task.Delay(1000); Debug.WriteLine("after"); return 5; } }
設定 Debug.WriteLine("before") 行設定中斷點在 DoSomethingAsync 方法。
這是為了示範 [步驟] 命令的行為從一行中不是第一行的非同步方法。
選擇 F5 鍵或選取 [偵錯],請在功能表列上的 [啟動偵錯] 啟動應用程式。
程式碼會在 DoSomethingAsync 方法的 Debug.WriteLine("before") 中斷。
選取 Shift+F11 鍵或選取 [偵錯],請在功能表列上的 [步驟] 。
應用程式在呼叫的方法會中斷與目前方法的工作等候陳述式。 因此,應用程式會在 ProcessAsync 方法中等候陳述式內容中斷。 應用程式在 Dim z = 0 (Visual Basic) 或 int z = 0; (C#) 中斷,為程式碼之後呼叫 DoSomethingAsync 方法。
選取 [偵錯],請在功能表列上的 [停止偵錯] 停止執行。
下列步驟示範發生的事情,當您從非同步方法的第一行中的 [步驟] 。
移除現有的中斷點,然後在 DoSomethingAsync 方法的第一行設定中斷點。
在 C# 中,將在 DoSomethingAsync 方法的左邊大括號的中斷點。 在 Visual Basic 中,將該行的中斷點會包含 Async Function DoSomethingAsync() As Task(Of Integer)。
選擇 F5 鍵啟動應用程式。
程式碼在 DoSomethingAsync 方法的第一個分行符號。
在功能表列上,選擇 [偵錯]],則 [視窗], [輸出]。
[輸出] 視窗隨即開啟。
選取 Shift+F11 鍵或選取 [偵錯],請在功能表列上的 [步驟] 。
應用程式繼續執行,直到非同步方法到達第一個等候,應用程式會中斷在後面的陳述式。 因此,應用程式在 Dim the Task = DoSomethingAsync() (Visual Basic) 或 var theTask = DoSomethingAsync(); (C#) 中斷。 「,」訊息會顯示在輸出視窗之前,不過, 「,」訊息不會出現。
選擇 F5 鍵繼續執行應用程式。
應用程式會繼續依照非同步呼叫的函式中的陳述式 (DoSomethingAsync) 的等候陳述式。 < 在訊息之後出現在輸出視窗中。