Делегат никогда не выполняется при вызове через Dispatcher.BeginInvoke с приоритетом ContextIdle. - PullRequest
0 голосов
/ 19 марта 2020

Я работаю над приложением WPF. У меня есть следующий код:

enter image description here

Но я никогда не получаю точку останова, которая ставится в начале метода ExpandFreeDraw:

enter image description here

Когда я вызываю метод BeginInvoke, я уже в потоке пользовательского интерфейса:

enter image description here

Метод ExpandFreeDraw также должен происходить в потоке пользовательского интерфейса. Я вызываю его с приоритетом незанятости контекста по следующей причине:

Перед строкой BeginInvoke я изменяю Видимость расширителя WPF с свернутого на Видимый. Он начинает рендеринг своих элементов управления: некоторые из этих элементов управления являются элементами управления вводом, и я хочу применить к ним проверку (выполняется с помощью AdornerDecorator, из-за чего у элемента управления ввода появляется красная граница проверки). Если я вызываю ExpandFreeDraw непосредственно после изменения видимости Expander (просто ExpandFreeDraw () без Dispatcher), я получаю точку останова в начале метода ExpandFreeDraw: расширитель виден, но флажок не применяется правильно - без красного эффект границы.

Я получаю тот же эффект с Dispatcher.BeginInvoke со следующим более низким приоритетом, который является фоновым:

enter image description here

In в этом случае я также получаю точку останова в начале метода ExpandFreeDraw. Когда я применяю следующий приоритет, который является ContextIdle, тогда воспроизводится моя проблема - я не достигаю упомянутой точки останова.

Обратите внимание, что эта функция работает большую часть времени, и именно так я знаю ContextIdle приоритет - мой желаемый приоритет, потому что он применяет проверку к элементам управления вводом в большинстве случаев (если я уменьшу приоритет до фона, он уже не будет). Это потому, что приоритет для Диспетчера - это 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 в большинстве случаев, но в одном из сценариев ios (что я не могу действительно понимаю, что) это не так? Как я могу отладить это?

Может быть:

enter image description here

Может ли фоновые операции никогда не завершаться? И поэтому операция с приоритетом ContextIdle никогда не выполняется? Как я могу это выяснить?

1 Ответ

0 голосов
/ 26 марта 2020

Я наконец-то решил это. Моя проблема заключалась в том, что очередь диспетчера пользовательского интерфейса постоянно получала действия с более высоким приоритетом (более высокий, чем в контекстном режиме ожидания).

Если вы напишите код в следующем виде:

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
Дополнительный фон
Context-Idle

Дополнительное действие Background выполняется перед действием context-idle, даже если оно было ставится в очередь в диспетчере очереди пользовательского интерфейса после действия бездействия контекста. Это тривиально, но важно понимать эту концепцию.

У меня был код, который проверяет, нахожусь ли я в потоке пользовательского интерфейса - если это так, немедленно выполните действие. В противном случае поставьте его в очередь диспетчера. Когда я принудительно упомянул упомянутое действие (ExpandFreeDraw) в очередь пользовательского интерфейса (даже если я уже был в потоке пользовательского интерфейса), все работало для меня: теперь вызывается действие, и я также получаю необходимую проверку.

...