C# 如何测试锁中的等待线程

C# 如何测试锁中的等待线程,c#,multithreading,locking,thread-safety,C#,Multithreading,Locking,Thread Safety,因此,我知道您可以使用信号量和其他可能的方法来确定锁是否会成功和/或有多少线程正在等待锁,但您可以从锁本身内部执行此操作吗 我的情况是,我有一个事件处理程序,可以被列表中的许多对象调用。我想在锁中做一个测试,看看所有对象在继续之前是否都处于正确的状态。对象转换到适当的状态,然后引发该事件,因此在单线程模型中,当最后一个引发该事件时,所有对象都将处于正确的状态,我们继续。但我突然想到,对于多个线程,多个对象可能会转换为我正在检查的状态,但由于它们正在等待锁,因此尚未处理此事件。因此,锁内的条件状态

因此,我知道您可以使用信号量和其他可能的方法来确定锁是否会成功和/或有多少线程正在等待锁,但您可以从锁本身内部执行此操作吗

我的情况是,我有一个事件处理程序,可以被
列表中的许多对象调用。我想在锁中做一个测试,看看所有对象在继续之前是否都处于正确的状态。对象转换到适当的状态,然后引发该事件,因此在单线程模型中,当最后一个引发该事件时,所有对象都将处于正确的状态,我们继续。但我突然想到,对于多个线程,多个对象可能会转换为我正在检查的状态,但由于它们正在等待锁,因此尚未处理此事件。因此,锁内的条件状态检查将为true,但在所有线程完成处理此事件之前,继续将是错误的。我需要它只有在最后一个线程被处理时才是真的,以确保我们不会进行得太快

例如,在半现实代码中:

object\u LockObj=newobject();
无效事件处理程序(对象发送方、事件参数)
{
MyObject发起人=作为MyObject的发送者;
如果(发起人==null)
返回;
*与发起人合作*
锁
{
if(listofMyObject.FindAll(o=>o.State==DesiredState)
.Count==ListofMyObject.Count
&&*锁上没有东西等待*)
{
*进行*
}
}
}
我完全准备好接受我的方法从一开始就很难闻,如果我首先正确地执行它,我正在寻找的解决方案是没有意义的,但是我不确定如何以线程安全的方式正确地执行它

我打算向
MyObject
添加更多的状态,并通过在
*与发起人一起做事*
部分中设置适当的状态来管理流,但从这里转换MyObject感觉不正确,更不用说,我必须为每个引发事件的状态实现一个保持状态,这个事件变得越来越臭,而不是越来越简单


因此,如果有一种简单的方法来执行“nothing waiting at the lock”(无需等待锁定)检查,那么这就是我想要的方法,除非我缺少一种在这种情况下非常简单的实现模式。

首先,不幸的是,测试等待lock()语句的其他线程并不能得到您想要的结果。例如,如果对象A、B和C已转换到所需的状态并引发了它们的事件,则有可能只为一个对象调用
事件处理程序
,例如此时的A。稍后,相同的处理程序将在某个时候为B和C运行。因此,您的所有对象现在都假定处于所需的状态,并且没有线程在锁处等待,但您可能会发现。不想“继续”。即使你这样做,你也需要考虑,同样的情况可能会在稍后的B发生,然后再次出现在C上,所以“继续”可能运行三次…

这是一个简单的建议,但您可以使用计数器来测试实际引发事件的对象数。如果计数器没有提供足够的信息,您也可以使用另一个列表。重要的一点是,无论使用哪种方法,在同一个
\u LockObj
上的锁中,只更新计数器/列表/其他机制。然后可能在继续运行后重置该计数器。如果您需要在其他地方访问计数器,请确保使用相同的
锁(\u 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;
        }
    }
}

编辑:删除了对象状态的冗余检查。

您考虑过简单的同步工作项队列吗?因此,当引发事件时,它只是将处理排队,并且处理由单独的线程按顺序完成?

在这一点上,双重检查不是没有用吗?如果If的两个部分不对齐,您将永远无法输入它。谢谢@xanatos,已经更新了代码。代码的其他部分可能会更新对象的状态,我们仍然需要检查它,但是如果是这样的话,我们应该(a)在这里看到更多的代码,(b)也应该假定,在其他部分中,计数器也改变它的值。(因此,无论我的解决方案是什么,我都需要独立跟踪完成情况,然后只有在我的独立测试成功后才能继续。感谢您的理智检查:)您要求将线程竞赛bug作为一项功能。在您得出没有线程等待的结论后的一纳秒,线程可以进入该方法。不确定这有什么帮助,除非您能够详细说明,因为我需要延迟进行,直到合适为止,问题是我现在如何继续。我将基于Jonno的实现一些东西以上回复(截止日期待定)除非出现更简单的方法。在单线程模型中,你说它工作得很好,可能你有一种机制来确定事件何时是最后一个被触发的。如果你在工作项中使用相同的逻辑,以便它可以确定它是否应该进行处理,那么你可以像对待单线程一样对待它。实际上,你是漏斗将多个线程引发的事件放入一个同步队列中,这样您就可以将其视为单个线程。我承认我可能匆忙给出了答案,所以我猜您实际上希望处理位异步,但其余的不是?