【问题标题】:WPF in WinForms: blocked on Dispatcher.Invoke although UI thread aliveWinForms 中的 WPF:尽管 UI 线程处于活动状态,但在 Dispatcher.Invoke 上被阻止
【发布时间】:2012-08-27 23:59:30
【问题描述】:

我们有一个嵌入在 WinForms 控件中的 WPF 控件,该控件又作为 ActiveX 控件公开。这个ActiveX最终用在了第三方开发的C++应用中。

在某些时候,ActiveX 控件的 UI 冻结,而 C++ 应用程序的其余部分运行良好。经过一些调试,我注意到 WPF 控件在每次调用 Application.Current.Dispatcher.Invoke 时都会被阻止。但是,WinForms 控件可以很好地处理它的 Control.Invoke 调用。每当我暂停调试器时,我可以看到 UI 线程正在 C++ 应用程序中做一些工作,但似乎没有被阻塞或等待任何事情。就好像 UI 线程突然莫名其妙地拒绝执行 WPF 委托。

当 C++ 应用程序长时间(几分钟)独占 UI 线程时,WPF 控件有时会进入此状态。我要做的第一件事是为这样一个耗时的任务使用不同的线程,但正如我已经说过的,我不对 C++ 应用程序正在做什么负责。无论如何,这不是我的 WPF 控件以这种方式运行的理由。我不知道如何解决这个问题;任何帮助将不胜感激。

【问题讨论】:

    标签: c# .net wpf user-interface freeze


    【解决方案1】:

    我建议运行 MS 调试诊断工具 - http://support.microsoft.com/kb/2580960

    我们使用它来识别 COM 互操作阻塞问题取得了很好的结果,在我们的案例中,这些问题归结为待处理的 COM 终结器阻塞垃圾收集。您可以在各种模式下运行它,但是当使用 .NET 分析运行时,它会突出显示终结器队列等的任何问题。运行起来有点笨拙,但它为您提供的信息是黄金。

    【讨论】:

      【解决方案2】:

      Invoke 的问题在于它的行为类似于多线程调用;但实际上并非如此,Invoke 正在阻塞——你仍然一次只允许一个线程。 Invoke 实际上只是确保在 UI 线程上执行操作。这是通过将消息强制进入消息泵并以这种方式执行来完成的。该操作可能会在调用Invoke 的线程需要执行以让操作继续执行的操作上被阻止。 例如:

      lock(someLock)
      {
          dispatcher.Invoke(SomeMethod);
      }
      
      //...
      
      public void SomeMethod()
      {
        lock(someLock)
        {
        //... do some work here
        }
      }
      

      在此示例中,Invoke 在持有锁的同时被阻止调用 SomeMethod。但是,SomeMethod 想要相同的lock,所以它被阻止等待lock。你有一个死锁。

      我建议改用BeginInvoke

      我不确定这是否是您的问题,因为您没有提供任何代码;但这是Invoke 的一个非常常见问题。通常没有理由需要Invoke;如果您认为有需要,这通常表明存在问题。

      【讨论】:

      • 感谢您的回答彼得。在您的示例中,主线程将被 SomeMethod 中的锁阻塞。就我而言,它没有被任何东西阻塞;我真的没有理由坚持调用。正如我所说,同一线程上 WinForm 中的调用工作得很好。显然是 WPF 调度程序由于某种原因不再响应。
      • @odsh 是的,这只是一个使用Invoke 而不是BeginInvoke 可能导致死锁的示例——尽管使用的是WinForms 而不是WPF。这同样适用于Dispatcher.Invoke/BeginInvoke。框架方法锁定在许多你不知道也无法控制的地方——导致你遇到类似的情况。您是否尝试改用Dispatcher.BeginInvoke
      • 我无法在我的应用程序中用 BeginInvokes 替换所有 Invokes;有时调用必须是同步的。无论如何,我不认为有死锁,否则主线程会被阻塞——他不是。如果按照您的建议,某个框架方法在某处被阻止,我想了解原因并纠正问题。丢弃调用,因为它们可能会在我不知道的地方随机导致死锁,这不是我的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      • 2015-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多