因為專案需求會透過參數去取得server上的副檔名 .ashx的檔案,
而必須在接到參數後在後端去仿照前端發request的動作而牽扯到async和await.....
題外話
.ashx就是一種http處理常式(定義: 為了回應對 ASP.NET Web 應用程式所提出之要求而執行的處理序。最普通的處理常式是處理 .aspx 檔案的 ASP.NET 網頁處理常式。當使用者要求 .aspx 檔案時,會透過網頁處理常式處理要求。)
簡而言之, .ashx的檔案就是只不包含UI但是目的也是用來處理request
正題開始
做一個簡單的畫面測試,
按下Async按鈕他會幫我在TextArea的地方把文字串上去
protected async void btnAsync_OnClick(object sender, EventArgs e)
{
//第一段
txtUserId.Text = "\n Start";
GetRemoteData();
txtUserId.Text += "\n End";
//第二段
txtUserId.Text = "\n Start";
txtUserId.Text += await GetRemoteDataAsync(); //呼叫自定義的GetRemoteDataAsync(), 注意回傳型態為Task<string>
txtUserId.Text += "\n End";
}
private async void GetRemoteData()
{
HttpClient hc = new HttpClient();
var result = await hc.GetStringAsync("http://localhost:54395/RemoteString.ashx");
txtUserId.Text += "\n" + result;
}
private async Task<string> GetRemoteDataAsync()
{
HttpClient hc = new HttpClient();
var result = await hc.GetStringAsync("http://localhost:54395/RemoteString.ashx");
return result;
}
假設上述程式片段呼叫 http://localhost:54395/RemoteString.ashx 時需要一段時間處理,
那第一段程式的結果會是
Start
End
回傳result
原因是定義 GetRemoteData() 前面多了關鍵字async, 會被視為非同步的method,
所以並不會等到這行程式被執行完才執行 txtUserId.Text += "\n End"; , 因此會先印出 End
而在GetRemoteData()中的關鍵字await, var result = await hc.GetStringAsync("http://localhost:54395/RemoteString.ashx");
而第二段的結果如下
Start
回傳result
End
要注意的是在最後定義GetRemoteDataAsync()的地方其回傳型態為 Task<string>, 表示其為awaitable的method,
所以在註解第二段以 txtUserId.Text += await GetRemoteDataAsync(); 來呼叫,
之後的程式碼會等到await執行完後再繼續
非同步方法可有下列傳回型別:
- Task
- Task<TResult>
- void,應該只用於事件處理常式。
簡單來說這個例子舉的方法會回傳string, 所以用 Task<string> 來當成傳回型別。
如果方法完成時未傳回任何有意義的值,則使用 Task。 也就是說,呼叫方法會傳回 Task,但是當 Task 完成時,等候 await
的任何 Task
運算式都會判斷值為 void。
使用 void 傳回類型定義需要該傳回類型的事件處理常式。 傳回 void 之非同步方法的呼叫端無法等候它,而且無法攔截方法擲回的例外狀況。
引用參考: http://studyhost.blogspot.tw/2012/06/metro-style-appnet-45.html