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();


}

这样的概念普遍吗?它有名字吗?我是在错误地处理事情吗?

4

2 回答 2

1

我最终创建了一个异步信号量,它工作得非常好,没有任何感觉。

于 2013-01-09T02:20:50.273 回答
0

通常你会为此目的使用 Mutex 或 Semaphores。例如,如果一个信号量只有一个标记,而一个操作已获取该标记,则在第一个操作完成并且标记已放回信号量之前,不能执行其他操作。

在您的第二个代码示例中,您刚刚调用了获取锁和释放锁,但是 sharedLock 不知道哪个操作调用了获取/释放。这就是为什么获得锁通常会返回一个令牌,该令牌可以在操作完成时被释放或释放。

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 作为您在获取锁上返回的令牌。操作完成后,只需调用 event.Set()

于 2013-01-04T10:10:58.933 回答