C# net中rasing事件的死锁
我遇到了一个奇怪的僵局。在附加visual studio之后。我看到3根线卡住了C# net中rasing事件的死锁,c#,.net,events,deadlock,C#,.net,Events,Deadlock,我遇到了一个奇怪的僵局。在附加visual studio之后。我看到3根线卡住了 线程1: if (SomeEvent != null) SomeEvent(this, new SomeArg) --> Stuck 线程2: if (SomeEvent2 != null) SomeEvent2(this, new SomeArg2) --> Stuck 主线程: public object (Delegate method, object[] args) {
if (SomeEvent != null)
SomeEvent(this, new SomeArg) --> Stuck
if (SomeEvent2 != null)
SomeEvent2(this, new SomeArg2) --> Stuck
public object (Delegate method, object[] args)
{
...
SynchronizationContext.Send(delegate(object state))
{
...
method.DynamicInvoke(args); --> Stuck
}
}
lock()
,或Monitor.Wait()
。我相信他们都坚持打外线电话
此外,我无法说出method.DynamicInvoke(args)
正在做什么,以及这个方法应该是什么
我唯一发现的是,附加的事件处理程序可能会导致死锁。然而,由于VS已经向我展示了这一点,这是它遇到的问题,而不是事件处理程序代码。我想可能是别的原因
就应用程序而言,我知道这是一个竞争条件,因为应用程序试图同时执行加载和卸载数据,所以这个问题很难重现
我的问题是:
关键是,事件和事件处理程序的代码如何执行并没有什么特别神奇的地方。虽然我将其简化到几乎肯定是错误的程度,但最基本的是,事件只是多播委托,可以公开地将元素添加到其调用列表或从其调用列表中移除,但所有其他表单访问都是私有的。没有与线程相关的事件。与以其他方式在事件处理程序中执行相同的代码相比,使用事件不会影响死锁的存在。对于您的第一条评论,VS stack显示引发事件在外部调用时被卡住。我假定外部调用意味着它不是托管代码。通常我希望事件不会返回,因为事件处理程序的代码是死锁。除非VS没有显示完整的堆栈。此外,事件处理程序的附加方式是典型的+=,没有任何自定义的事件订阅代码。我的观点是,事件与正常的代码执行过程并没有什么不同,我将编辑我的答案以添加更多的信息。通过外部调用,我假设您的意思是调用堆栈显示
[external code]
。外部代码只是意味着VisualStudio不认为它是您的用户代码。您可以在调用堆栈窗口上单击鼠标右键,然后从关联菜单中选择“显示外部代码”。当您这样做时,您可能会看到一个[本机到托管转换]
,这就是您离开托管代码的地方。这或许能让我们对僵局的性质有所了解。