2013-01-04 20 views
1

我有一個可以更改內部狀態的類。爲異步應用設計的鎖

這些狀態變化是決不簡單,並且通常由在多個線程中發生幾個異步操作,如打開的連接,併發送一些數據

通過使用鎖定和一個布爾值,指示所述狀態是否是目前改變我可以確保只有一個操作都不能在任何給定的時間

lock (thisLock) { 

    while (stateChanging) 
     Monitor.Wait(thisLock); 


    stateChanging= true; 

    //now free to go away and do other things while maintaining exclusive access to the inner state 


} 

這工作得很好,獲得了國家,但它意味着在線程出現等待獲得獨家獲得的國家不必要的阻塞

所以我設想是基於回調,其中狀態改變操作鎖不這樣的事情 -

sharedLock.ObtainLock(delegate() { 

    //we now have exclusive access to the state 
    //do some work 

    socket = new Socket(); 
    socket.BeginConnect(hostname, connectcallback); 

}); 

void connectcallback(IAsyncResult result) { 

    socket.EndConnect(result); 

    isConnected = true; 

    sharedLock.ReleaseLock(); 


} 

就是這樣一個概念,什麼共同點?它有名字嗎?我錯誤地接近事物嗎?

回答

0

通常你會使用互斥或​​信號來達到這個目的。例如,如果一個信號量只有一個令牌並且一個操作取得了該令牌,那麼在第一個操作完成並且該令牌已經回到信號量之前,不能執行其他操作。

在第二個代碼示例中,您只需調用ObtainLock和ReleaseLock,但是然後sharedLock不知道哪個操作稱爲獲取/釋放。這就是爲什麼ObtainLock通常會返回一個令牌,可以在操作完成時插入或釋放。

IDisposable myLock; 

myLock = sharedLock.ObtainLock(delegate() { 
    socket = new Socket(); 
    socket.BeginConnect(hostname, connectcallback); 
}); 

void connectcallback(IAsyncResult result) { 
    socket.EndConnect(result); 
    isConnected = true; 
    myLock.Dispose(); 
} 

實現你sharedLock管理這些標記,並根據每個國家令牌它知道,如果它是忙或沒有的類。其實無非就是一個參考櫃檯。

作爲另一種選擇,您可以使用ManualResetEvent或AutoResetEvents作爲您在ObtainLock上返回的標記。當你的操作完成後,只需調用event.Set()

+0

這很有用,謝謝 – NoPyGod

+0

很高興幫助;) – Matthias

1

我最終創建了一個異步信號量,它的工作真的很好,沒有任何感覺哈克。