有許多耗時操作時,還要響應用戶操作。這時候就需要用其他線程或者異步來搞。本來是改造公司的日志組件。因為多上了個國外大區的業務到來本系統來。這個系統其他地方都好就是日志,動不動就要死給我們看。有時候尋找業務流程時缺失了一塊日志,令人欲仙欲死。剛好年末了沒什麼業務上線,決定改造日志。前人栽樹後人心涼。本著我不入地獄誰入地獄的精神,折騰完了這個日志。發現線程的有些地方處理的不好。順帶給自己留個念想謝謝異步或者多線程的東西。有錯誤歡迎指正。
1. 使用歷史
這兩個是以前好早就有的,在.net框架內用的比較廣泛,比如引用webservice時,除了自動生成同步的方法,還會生成異步調用的方法。
隨著.net版本的不同有直接封裝成 beginXXXX 和endXXXX的,使用時直接begin,然後處理一些事情,然後再end.不過有個缺點就是固定的方法太死。
後來webservice就封裝了下,弄個complete後綴的委托,來事件通知調用結束了。然後調用方法直接是AsycXXXX。跟自己寫控件時往上層拋事件差不多。
還有就是IO和網絡編程的一些類實現這個,比如NetworkStream 中的讀和寫都有同步和異步的方法。
對於這兩個使用方式如果使用,可以直接在一個方法內begin end在他們之間搞些事情。不過這樣太死板了。一般是給個委托操作。
看如下代碼:
public delegate bool deofdosomething(object param); public void invoketest() { Console.WriteLine("star.."); //耗時操作的傳遞參數 object dosomeparam = "1"; //耗時方法執行結束,回調函數可以得到的參數 object endinvokeparam = "2"; deofdosomething de = new deofdosomething(dosomething); AsyncCallback acb = new AsyncCallback(invokecallback); IAsyncResult iar = de.BeginInvoke(dosomeparam, acb, endinvokeparam); if (iar.AsyncWaitHandle.WaitOne(1000)) { Console.WriteLine("not time out"); } else { Console.WriteLine("time out"); } } private bool dosomething(object obj) { //耗時操作 Thread.Sleep(2000); //dosomeparam Console.WriteLine(obj.ToString()); return true; }
AsyncCallback 是.net框架內一個特殊的委托,在異步調用後如果已經執行完成,可以通過這個委托來通知。當然也可用傳入null。代表不根據結果操作什麼。
iar.AsyncWaitHandle.WaitOne 這個是begin後的語句句柄,可以用來設定是否等待異步超時。跟autoresetevent一樣設置超過超時時間立馬返回。懷疑裡面就是用的這玩意實現的。
會返回個布爾類型的值,如果沒有超時這個值是TRUE,如果超時了這個值是FALSE。
private void invokecallback(IAsyncResult iar) { deofdosomething de = (deofdosomething)((AsyncResult)iar).AsyncDelegate; //endinvokeparam string targeparam = ((AsyncResult)iar).AsyncState.ToString(); Console.WriteLine(targeparam); //dosomething 有返回值 bool issuccess = de.EndInvoke(iar); Console.WriteLine("end"); }
IAsyncResult 是異步操作完成的委托傳過來執行的方法。作為一個接口可以直接轉成 AsyncResult ,它的AsyncDelegate 是可以獲取到引用它的委托。
AsyncState 是個object類型的參數,是從begin傳來的參數,因為異步操作可以帶來一些額外的信息。
一下是測試結果。有人來鬧我,等改天再寫吧。預計寫threadpool還有task兩個。希望能堅持。