在上一篇文章中 Async Await , C# 編譯器做了些甚麼事情呢– 1,我們將 WPF 內的非同步程式碼,透過編譯器的處理,產生了相對應的狀態機程式碼,並且在產生後的程式碼中,加入了詳盡的註解說明,並且說明了編譯器的處理過程。
在這篇文章中,我們將要補足上篇文章的一些不足點,那就是,在我們呼叫非同步程式之前,也就是 await 關鍵字之前,若還有些 C# 程式碼的話,而且,在這 await 關鍵字之後,繼續有使用到這些變數,那麼,在編譯器中所產生的狀態機物件會如何呈現?
(至於,同一個非同步方法中,若有多個 await 關鍵字,則狀態機內會使用 goto 來切換到不同的部分還處理,有興趣的人,可以自行針對編譯器產生結果程式碼來觀察)
底下為我在 WPF 的按鈕事件內呼叫一個非同步方法,在呼叫非同步方法之前,我們會計算 x * y * z 的數學運算結果到本地變數 total 內;並且在呼叫完成非同步方法之後,再將 total 變數的值,輸出到 Console上。
private async void btnDownload2_Click(object sender, RoutedEventArgs e)
{
int x = 3, y = 1, z = 2, total = 0;
total = x * y * z;
string fooStr = await GetString2Async();
Console.WriteLine(string.Format("{0} {1}", total,fooStr));
}
接著我們來看看,經過了編譯器的轉換,狀態機的類別,會如何定義呢?
我們特別將呼叫 await 非同步方法前的程式碼使用黃底色標示出來,而呼叫完成非同步方法之後的程式碼使用橘底色標示出來,您可以參考上一篇文章 Async Await , C# 編譯器做了些甚麼事情呢– 1 ,試著找出其中異同點。
[CompilerGenerated]
private sealed class <btnDownload2_Click>d__3 : IAsyncStateMachine
{
public int <>1__state;
public AsyncVoidMethodBuilder <>t__builder;
public object sender;
public RoutedEventArgs e;
public MainWindow <>4__this;
private int <x>5__1;
private int <y>5__2;
private int <z>5__3;
private int <total>5__4;
private string <fooStr>5__5;
private string <>s__6;
private TaskAwaiter<string> <>u__1;
void IAsyncStateMachine.MoveNext()
{
int num = this.<>1__state;
try
{
TaskAwaiter<string> taskAwaiter;
if (num != 0)
{
this.<x>5__1 = 3;
this.<y>5__2 = 1;
this.<z>5__3 = 2;
this.<total>5__4 = 0;
this.<total>5__4 = this.<x>5__1 * this.<y>5__2 * this.<z>5__3;
taskAwaiter = this.<>4__this.GetString2Async().GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.<>1__state = 0;
this.<>u__1 = taskAwaiter;
MainWindow.<btnDownload2_Click>d__3 <btnDownload2_Click>d__ = this;
this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter<string>, MainWindow.<btnDownload2_Click>d__3>(ref taskAwaiter, ref <btnDownload2_Click>d__);
return;
}
}
else
{
taskAwaiter = this.<>u__1;
this.<>u__1 = default(TaskAwaiter<string>);
this.<>1__state = -1;
}
string result = taskAwaiter.GetResult();
taskAwaiter = default(TaskAwaiter<string>);
this.<>s__6 = result;
this.<fooStr>5__5 = this.<>s__6;
this.<>s__6 = null;
Console.WriteLine(string.Format("{0} {1}", this.<total>5__4, this.<fooStr>5__5));
}
catch (Exception exception)
{
this.<>1__state = -2;
this.<>t__builder.SetException(exception);
return;
}
this.<>1__state = -2;
this.<>t__builder.SetResult();
}
[DebuggerHidden]
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
}
}
沒有留言:
張貼留言