所以我知道你可以使用信号量和可能的其他方法来确定锁是否会成功和/或有多少线程在等待锁,但是你可以在锁本身内执行此操作吗?
我的情况是我有一个事件处理程序,可以被List
内的许多对象调用。我想在锁内进行测试,看看在继续之前所有对象是否都处于正确的状态。对象转换到适当的状态然后引发此事件,因此当最后一个引发此事件时,在单个线程模型中,所有对象将处于正确状态,然后我们继续。但是我发现,使用多个线程,多个对象可能会转换到我正在检查的状态,但是当它们在锁定时等待时尚未处理此事件。因此,锁内的条件状态检查将为true,但是在所有线程完成处理此事件之前,进程将会很糟糕。我需要它才真实,因为最后一个线程被处理以确保我们不会太快进行。
例如在半现实代码中:
object _LockObj = new object();
void Event_Handler(object sender, EventArgs e)
{
MyObject originator = sender as MyObject;
if(originator == null)
return;
*Do stuff with the originator*
lock(_LockObj)
{
if(ListOfMyObjects.FindAll(o => o.State == DesiredState)
.Count == ListOfMyObjects.Count
&& *nothing waiting at the lock*)
{
*Proceed*
}
}
}
我完全准备接受我的方法是臭臭的开始,我正在寻找的解决方案是没有实际意义,如果我正确地做到这一点,但我不确定如何在一个线程中正确地做到这一点安全的方式。
我打算向MyObject
添加更多状态,并通过在*Do stuff with the originator*
部分设置适当的状态来管理流程,但是从这里转换MyObject感觉不正确,而不是提到我然后必须为每个州实施一个持有状态,这个状态会引发一个越来越简单的事件!
因此,如果有一种简单的方法可以执行“无需等待锁定”检查那么这就是我想去的方式,除非我错过了一个非常简单的实现模式在这种情况下有所帮助。
答案 0 :(得分:3)
首先,不幸的是,测试等待lock()语句的其他线程将无法获得您想要的结果。例如,如果对象A,B和C已转换到所需状态并已提升其事件,则Event_Handler
可能仅针对一个对象调用,例如在该点处为A.稍后将在某个时刻为B和C运行相同的处理程序。因此,现在所有的对象都处于所需的状态,并且没有线程在锁定等待,但是你有问题。不想“继续”。即使你这样做,你也需要考虑,同样的事情可能会在B之后发生,然后再次发生在C上,所以“继续”可能会运行三次......
这是一个简单的建议,但您可以使用计数器来测试实际引发事件的对象数量。如果计数器没有提供足够的信息,您也可以使用另一个列表。重要的是,无论您使用哪种方法,只需在同一_LockObj
内锁定时更新计数器/列表/其他机制。然后可能在继续运行后重置该计数器。如果您需要访问其他地方的计数器,请确保使用相同的lock(_LockObj)
,这将确保您在其他关键部分内不会更改它。
object _LockObj = new object();
int _counter = 0;
void Event_Handler(object sender, EventArgs e)
{
MyObject originator = sender as MyObject;
if(originator == null)
return;
*Do stuff with the originator*
lock(_LockObj)
{
++_counter;
if (_counter == ListOfMyObjects.Count)
{
*Proceed*
_counter = 0;
}
}
}
编辑:删除了对象状态的冗余检查。
答案 1 :(得分:1)
您是否考虑过简单的同步工作项队列?因此,当事件被引发时,它只是将处理排队,处理是由一个单独的线程按顺序完成的?