在.net中发生事件的僵局

时间:2011-07-28 16:20:03

标签: c# .net events deadlock

我有一个奇怪的僵局情况。附加视觉工作室。我看到3个线程卡住了。

  1. 主题1:

    if (SomeEvent != null)
       SomeEvent(this, new SomeArg) --> Stuck
    
  2. 主题2:

    if (SomeEvent2 != null)
        SomeEvent2(this, new SomeArg2) --> Stuck
    
  3. 主线程:

    public object (Delegate method, object[] args)
    {
       ...
       SynchronizationContext.Send(delegate(object state))
       {
           ...
           method.DynamicInvoke(args); --> Stuck
       }
    }
    
  4. 这三个线程被卡住,当我检查他们的调用堆栈时,我无法找到任何共享资源,例如lock()Monitor.Wait()。我相信他们都坚持外部电话。

    另外,我不知道method.DynamicInvoke(args)正在做什么以及这种方法应该是什么。

    我发现的唯一一件事是附加的事件处理程序可能会导致死锁。但是,因为VS已经告诉我这是它停留的地方,而不是事件处理程序代码。我认为这可能是别的。

    在应用程序方面,我知道这是竞争条件,因为应用程序试图在同一时间执行加载和卸载数据,因此这个问题很难重现。

    我的问题是:

    1. 为什么.NET线程在引发事件时会挂起,是否可能?
    2. 引发事件时是否需要使用主UI线程?
    3. 如果事件确实可能导致死锁,我应该如何防止这种情况发生呢?
    4. 由于

1 个答案:

答案 0 :(得分:1)

  1. 筹集活动时线程是否可能会挂起?是的。在事件处理程序完成之前,执行的线程不会从事件的引发返回。事件处理程序可以是任何东西,因此它们可以挂起。如果事件处理程序挂起,则事件引发线程将挂起。

  2. 不,主UI线程不需要用于引发事件。任何线程都可以引发事件。

  3. 事件提升不是特别容易发生死锁,但它也不能免疫。当您引发事件时,您所在的线程将执行已注册为事件处理程序的任何代码。那段代码并不特别。它只是在引发事件的同一线程上执行的代码。由于所有代码都可以死锁的相同原因,它可能会死锁。

  4. 重点是关于事件和事件处理程序的代码如何执行没有什么特别神奇的。虽然我简化到几乎肯定是错的,但基本的是事件只是多播委托,可以公开地在其调用列表中添加和删除元素,但所有其他表单访问都是私有的。没有与线程相关的事件。与在事件处理程序中以其他方式执行相同代码相比,使用事件不会影响死锁的存在。