2013-01-04 36 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

我最终创建了一个异步信号量,它的工作真的很好,没有任何感觉哈克。