為了不阻塞UI,在windows phone的多線程上完全去掉了同步的模型,全部使用非同步模型來處理請求。
這樣帶來的好處是UI不會被卡死,能夠一直響應使用者的響應,將比較耗時的操作丟給後台線程處理,並且能避開線程同步的麻煩。
但這樣一來,寫出來的代碼也比較難看,還可能涉及到資料共用的問題。
我相信如果你的應用涉及到HttpRequest的話那麼一定會遇到我說的情況。
歡迎大家一起討論你的思路。
以下是幾種我常用的非同步請求代碼的模型
1、使用匿名函數,有時候為了節約會使用lamda運算式
2、事件模式,通過訂閱請求完成事件
3、Async CTP
第一種方式的代碼如下:
private string Reqest() { string resultString = string.Empty; HttpWebRequest request = HttpWebRequest.CreateHttp("http://www.google.com"); request.Method = "GET"; request.BeginGetResponse((IAsyncResult result) => { HttpWebRequest webRequest = result.AsyncState as HttpWebRequest; HttpWebResponse webResponse = (HttpWebResponse)webRequest.EndGetResponse(result); Stream streamResult = webResponse.GetResponseStream(); StreamReader reader = new StreamReader(streamResult); //擷取的傳回值 resultString = reader.ReadToEnd(); }, request); return resultString; }
-
第二種方式的代碼如下:
public delegate void GetResultEventHandler(object sender, string e); public event GetResultEventHandler OnGetInfoCompleted; private void Reqest() { HttpWebRequest request = HttpWebRequest.CreateHttp("http://www.google.com"); request.Method = "GET"; request.BeginGetResponse(GetInfoCompleted, request); } protected void GetInfoCompleted(IAsyncResult asyncResult) { try { HttpWebRequest webRequest = asyncResult.AsyncState as HttpWebRequest; HttpWebResponse webResponse = (HttpWebResponse)webRequest.EndGetResponse(asyncResult); Stream streamResult = webResponse.GetResponseStream(); StreamReader reader = new StreamReader(streamResult); //擷取的傳回值 string resultString = reader.ReadToEnd(); if (OnGetInfoCompleted != null) { OnGetInfoCompleted(this, resultString); } } catch (WebException ex) { MessageBox.Show(ex.Message); } }
第三種方式的代碼實現如下:
private async resultString Reqest() { HttpWebRequest request = HttpWebRequest.CreateHttp("http://www.google.com"); request.Method = "GET"; HttpWebResponse webResponse = await request.GetResponseAsync(); Stream streamResult = response.GetResponseStream(); StreamReader reader = new StreamReader(streamResult, new GB2312.GB2312Encoding()); string resultString = reader.ReadToEnd(); return resultString; }
-
因為有時候請求會有嵌套關係,比如在請求第二個資料之前,需要先請求第一個資料,所以用第一種方式會一直匿名很多層,讓我覺得很不爽。
在沒有async CTP for windows phone之前,我一直用第二種方式來寫代碼,因為這樣邏輯比較清楚。只是事件的模型看起來也不完美,但這也算是比較常用的非同步模型,用事件來傳遞參數。缺點是當邏輯需要阻塞線程的時候,卻又阻塞不了。
我想這也是async架構出現的原因吧。
在windows8的開發中,async架構已成為正式版,也就是說已經完全支援了第三種非同步模型,也就是以async,await為主導的模型。這樣即可以讓需要等待的代碼阻塞著,又可以讓UI線程保持通暢,並且代碼的邏輯也能很清楚,又避開了線程同步的資料鎖的麻煩。
算是在這件事情上現階段較為完美的方案了。
拋磚引玉,大家積極討論。