Подтвердить что ты не робот

InvokeRequired в wpf

Я использовал эту функцию в приложении Windows forms:

delegate void ParametrizedMethodInvoker5(int arg);

private void log_left_accs(int arg)
{
    if (InvokeRequired) 
    {
        Invoke(new ParametrizedMethodInvoker5(log_left_accs), arg);
        return;
    }

    label2.Text = arg.ToString();
}

Но в WPF он не работает. Почему?

4b9b3361

Ответ 1

В WPF метод Invoke находится в диспетчере, поэтому вам нужно вызвать Dispatcher.Invoke вместо Invoke. Кроме того, нет свойства InvokeRequired, но диспетчер имеет метод CheckAccess (по какой-то причине он скрыт в intellisense). Поэтому ваш код должен быть:

delegate void ParametrizedMethodInvoker5(int arg);
void log_left_accs(int arg)
{
    if (!Dispatcher.CheckAccess()) // CheckAccess returns true if you're on the dispatcher thread
    {
        Dispatcher.Invoke(new ParametrizedMethodInvoker5(log_left_accs), arg);
        return;
    }
    label2.Text= arg.ToString();
}

Ответ 2

В WPF используйте метод CheckAccess вместо InvokeRequired

if (!CheckAccess()) { 
  // On a different thread
  Dispatcher.Invoke(() => log_left_accs(arg));
  return;
}

Ответ 4

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

Вы должны использовать Dispatcher.Invoke для добавления делегата в поток пользовательского интерфейса в приложении WPF.

Также стоит отметить, что InvokeRequired действительно не требуется в приложении winform, и это не то, что вы должны проверять в приложении WPF. Вы должны знать, что вы не находитесь в потоке пользовательского интерфейса при вызове Invoke. Вы никогда не должны находиться в ситуации, когда данный метод иногда вызывается из потока пользовательского интерфейса и иногда вызывается из фонового потока. Выбери один; либо всегда заставляют вызывающего абонента ссылаться на поток пользовательского интерфейса перед вызовом заданного метода (поэтому вам не нужно вызывать) или предположить, что вызывающий объект не будет в потоке пользовательского интерфейса при вызове метода. Также стоит отметить, что вызов Invoke, когда вы уже находитесь в потоке пользовательского интерфейса, отлично. Нет ошибок или проблем, которые могут возникнуть из-за случайного экземпляра повторного вызова потока пользовательского интерфейса (там очень низкая стоимость исполнения, поэтому просто не добавляйте ненужный код для него повсюду).