業務場景如下:WPF應用程序后臺有個定時任務在接收PLC硬件數據(該線程接收完數據之后, 會重新啟動一個新線程繼續接收.....),當應用程序關閉時, 我們得確保接收PLC硬件數據的線程完成之后,再關閉應用程序,否則會造成數據丟失。
上面的業務場景是前一段時間一個朋友向我請教WPF的問題,項目中有一個ManualResetEventSlim類 ,不知道這個類是干什么的。由于本人從事WPF的工作將近10年,在項目中用到過不少與線程相關聯的類,所以在這做個簡單介紹,做過C/S架構的朋友對多線程接觸會更多,那么線程與線程之間是如果通信呢?就是通過ManualResetEventSlim類來完成,其實這個類和ManualResetEvent功能上是一樣。ManualResetEventSlim 更輕量級一些。我們解釋一下這個類具體用法:
static?void?MRES_SetWaitReset()
{System.Threading.ManualResetEventSlim mres1 = new System.Threading.ManualResetEventSlim(false); // initialize as unsignaledSystem.Threading.ManualResetEventSlim mres2 = new System.Threading.ManualResetEventSlim(false); // initialize as unsignaledSystem.Threading.ManualResetEventSlim mres3 = new System.Threading.ManualResetEventSlim(true); // initialize as signaled// Start an asynchronous Task that manipulates mres3 and mres2var observer = Task.Factory.StartNew(() =>{mres1.Wait();Console.WriteLine("observer sees signaled mres1!");Console.WriteLine("observer resetting mres3...");mres3.Reset(); // should switch to unsignaledConsole.WriteLine("observer signalling mres2");mres2.Set();});Console.WriteLine("main thread: mres3.IsSet = {0} (should be true)", mres3.IsSet);Console.WriteLine("main thread signalling mres1");mres1.Set(); // This will "kick off" the observer Taskmres2.Wait(); // This won't return until observer Task has finished resetting mres3Console.WriteLine("main thread sees signaled mres2!");Console.WriteLine("main thread: mres3.IsSet = {0} (should be false)", mres3.IsSet);// It's good form to Dispose() a ManualResetEventSlim when you're done with itobserver.Wait(); // make sure that this has fully completedmres1.Dispose();mres2.Dispose();mres3.Dispose();
}
當前方法有兩個線程:主線程和oberver子線程。應用程序運行時,這兩個線程同時執行,oberver子線程調用mres1.Wait(),所以使oberver子線程處于等待。主線程繼續運行,當調用mres1.Set()主線程會給oberver子線程發個信號,主線程對oberver子線程說:"ok,oberver子線程你可以繼續運行了",這時oberver線程mres1.Wait()收到該信號后,不再等待,繼續執行下面代碼。主線程執行到 mres2.Wait();方法時,這時主線程會掛起,處于等待狀態,這時oberver子線程繼續執行,當oberver子線程運行到mres2.Set();?oberver子線程會給主線程發送一個信號,oberver子線程會對主線程說:"OK,主線程可以運行了",于是mres2.Wait()不再等待,會繼續運行. OK, 這就是這個方法的大體執行流程.
總結:ManualResetEventSlim類
Wait()方法內部檢測到IsSet屬性的值,如果為false,線程會掛起。如果為IsSet為ture,線程不會掛起會繼續執行。
Reset()會將IsSet設置成false。
Set() 會將這IsSet設置成true。?
備注:Wait()內部通過輪訓來判斷這個值.來決定時候處于等待狀態。