Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# net中rasing事件的死锁_C#_.net_Events_Deadlock - Fatal编程技术网

C# net中rasing事件的死锁

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) {

我遇到了一个奇怪的僵局。在附加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)
    {
       ...
       SynchronizationContext.Send(delegate(object state))
       {
           ...
           method.DynamicInvoke(args); --> Stuck
       }
    }
    
  • 这三个线程被卡住了,当我检查它们的调用堆栈时,我无法找到任何共享资源,如
    lock()
    ,或
    Monitor.Wait()
    。我相信他们都坚持打外线电话

    此外,我无法说出
    method.DynamicInvoke(args)
    正在做什么,以及这个方法应该是什么

    我唯一发现的是,附加的事件处理程序可能会导致死锁。然而,由于VS已经向我展示了这一点,这是它遇到的问题,而不是事件处理程序代码。我想可能是别的原因

    就应用程序而言,我知道这是一个竞争条件,因为应用程序试图同时执行加载和卸载数据,所以这个问题很难重现

    我的问题是:

  • 为什么.NET线程在引发事件时会挂起,这可能吗
  • 引发事件时是否需要使用主UI线程
  • 如果事件确实有可能陷入僵局,我应该如何防止
  • 谢谢

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

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

  • 事件引发并不特别容易出现死锁,但它也不能免疫死锁。当您引发事件时,您所在的线程将执行任何已注册为事件处理程序的代码。那代码并不特别。它只是在引发事件的同一线程上执行的代码。它可以死锁,也可以不死锁,原因与任何代码都可能死锁相同


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

    对于您的第一条评论,VS stack显示引发事件在外部调用时被卡住。我假定外部调用意味着它不是托管代码。通常我希望事件不会返回,因为事件处理程序的代码是死锁。除非VS没有显示完整的堆栈。此外,事件处理程序的附加方式是典型的+=,没有任何自定义的事件订阅代码。我的观点是,事件与正常的代码执行过程并没有什么不同,我将编辑我的答案以添加更多的信息。通过外部调用,我假设您的意思是调用堆栈显示
    [external code]
    。外部代码只是意味着VisualStudio不认为它是您的用户代码。您可以在调用堆栈窗口上单击鼠标右键,然后从关联菜单中选择“显示外部代码”。当您这样做时,您可能会看到一个
    [本机到托管转换]
    ,这就是您离开托管代码的地方。这或许能让我们对僵局的性质有所了解。