UI线程中与Dispatcher.PushFrame和Application.DoEvents的互斥操作



的情况

我试着用一个小例子来解释我的问题。我有一个管理视图堆栈的类。替换视图显示并初始化它们等。

class ViewManager()
{
    void ReplaceView()
    {
        RemoveView(...);
        InitializeView(...); // this code may call Application.DoEvents()
        AddNewView(...);
    }
    void ShowModalView()
    {
        ShowView();
        Dispatcher.PushFrame()
        ....
        // wait until view can be removed
        RemoveView();
    }
   void RemoveView()
   {
     ...
   }
   // ... more functions
}

因为ViewManager对UI元素做了很多工作,所以其他线程通过Dispatcher.Invoke.使用ViewManager

Dispatcher.Invoke(new Action(() => m_viewManager.Remove(someView)));

如果现在多个线程在ViewManager上调用操作,并且其中一个线程在代码Application.DoEvents或DispatcherPushFrame中的某个地方调用,则会生成第二个MessageLoop,它将调用视图管理器上的另一个方法。

问题:

  • 调用ShowModalView并调用PushFrame
  • 在ShowModalView期间,另一个线程调用ShowModalView或ReplaceView
  • 因为新的消息循环执行排队到调度器的所有任务,所以也执行该方法
  • 因此,ViewManager的两个方法"同时"执行——或者更好,因为它是同一个线程——相互嵌套

ViewManager内部的锁定是无用的,因为它都是同一个线程。信号量可能会冻结UI线程,因为在"ShowModalView"的Message循环期间,另一个线程可以调用调度器上的ShowModalView,这将冻结UI线程。

问题:

  • 在"ShowModalView"期间,UI线程应该处理输入/绘制等,但不应该处理通过"Dispatcher.Invoke"调用的其他任务。这可能吗
  • 你有其他想法来解决这个问题吗

谢谢你的提示和答案

Manuel

编辑:一种解决方案可能是去掉所有DoEvents和PushFrame代码。这很难实现,但可能是唯一正确的解决方案。这篇文章解释了我的问题的一部分

Application.DoEvents 的使用

正如Servy所说,去掉Application.DoEvents((和Dispatcher.PushFrame是唯一干净的解决方案。有时这会导致大量重构,但这是值得的。

相关内容

  • 没有找到相关文章

最新更新