有許多耗時操作時,還要響應用戶操作。這時候就需要用其他線程或者異步來搞。本來是改造公司的日志組件。因為多上了個國外大區的業務到來本系統來。這個系統其他地方都好就是日志,動不動就要死給我們看。有時候尋找業務流程時缺失了一塊日志,令人欲仙欲死。剛好年末了沒什麼業務上線,決定改造日志。前人栽樹後人心涼。本著我不入地獄誰入地獄的精神,折騰完了這個日志。發現線程的有些地方處理的不好。順帶給自己留個念想謝謝異步或者多線程的東西。有錯誤歡迎指正。
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兩個。希望能堅持。