Delegate永远不会在通过Dispatcher.BeginInvoke以ContextIdle优先级调用时执行

问题描述 投票:-3回答:1

我正在处理WPF应用程序。我有以下代码:

enter image description here

但是我从来没有到达ExpandFreeDraw方法开始处的断点:

enter image description here

[当我调用BeginInvoke方法时,我已经在UI线程上:

enter image description here

ExpandFreeDraw方法也应在UI线程上发生。由于以下原因,我以上下文空闲优先级调用它:

在BeginInvoke行之前,我将WPF扩展器的可见性从折叠更改为可见。它开始呈现其控件:其中一些控件是输入控件,我想对其进行验证(通过AdornerDecorator完成,使其看起来像输入控件具有红色的验证边框)。如果我在更改Expander的可见性后直接调用ExpandFreeDraw(只是在没有Dispatcher的ExpandFreeDraw()的情况下),那么我确实会到达ExpandFreeDraw方法开始处的断点:扩展器可见,但装饰器未正确应用-没有红色边框效果。

我使用下一个较低的优先级(即背景:Dispatcher.BeginInvoke获得相同的效果:

enter image description here

在这种情况下,我还可以在ExpandFreeDraw方法的开头到达断点。当我应用下一个优先级(即ContextIdle)时,就会重现我的问题-我没有到达提到的断点。

请注意,此功能在大多数情况下都有效,这就是我知道ContextIdle优先级是我想要的优先级,因为在大多数情况下,它确实将验证应用于输入控件(如果我将优先级降低为Background,则它已经没有)。这是因为赋予Dispatcher的优先级是ContextIdle,它比Render的优先级低-您可以在此处了解更多信息:http://www.jonathanantoine.com/2011/08/29/update-my-ui-now-how-to-wait-for-the-rendering-to-finish/)。

我想获得有关如何找出问题所在的帮助。为什么

enter image description here

在大多数情况下正确调用ExpandFreeDraw的方法,但是在其中一种情况下(我无法真正理解哪种情况),它不是吗?我该如何调试?

也许:

enter image description here

可能是后台操作从未完成?这就是为什么永远不执行具有ContextIdle优先级的操作的原因?如何解决?

wpf dispatcher begininvoke
1个回答
0
投票

我终于解决了。我的问题是,UI调度程序队列不断以较高的优先级(高于上下文空闲)来获取操作。

如果您按以下方式编写代码:

public MainWindow()
    {
        InitializeComponent();
        Thread t = new Thread(() =>
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(() => DoBackGround1()), DispatcherPriority.Background, null);
            Application.Current.Dispatcher.BeginInvoke(new Action(() => Debug.WriteLine("Context-Idle")), DispatcherPriority.ContextIdle, null);
            Application.Current.Dispatcher.BeginInvoke(new Action(() => Debug.WriteLine("Additional-Background")), DispatcherPriority.Background, null);



        });
        t.Name = "dispatcherTest";
        t.Start();
    }


    private void DoBackGround1()
    {
        for (int i = 0; i < 10; i++)
        {
            Thread.Sleep(1000);
            Debug.WriteLine("Background " + i);
        }
    }

您将在输出窗口中获得以下结果:

背景0背景1背景2背景3背景4背景5背景6背景7背景8背景9附加背景上下文空闲

Additional-Background操作是在context-idle操作之前执行的,即使它是在context-idle操作之后被排队到UI队列调度程序中的。这很简单,但是了解这个概念很重要。

我有一个代码检查我是否在UI线程上-如果是,请立即执行操作。否则,将其排入调度程序队列。当我将提到的动作(ExpandFreeDraw)强制进入UI队列(即使我已经在UI线程上)时,一切都对我有用:现在,该动作被调用,并且我还获得了所需的验证。

© www.soinside.com 2019 - 2024. All rights reserved.