Использование методов VerifyAccess и CheckAccess в DispatcherObject - PullRequest
3 голосов
/ 06 сентября 2010

Проходя через эту статью, я наткнулся на это утверждение -

Если вы пишете свои собственные объекты WPF, такие как элементы управления, все используемые вами методы должны вызывать VerifyAccess доони выполняют любую работу.Это гарантирует, что ваши объекты используются только в потоке пользовательского интерфейса, как это

//Using VerifyAccess and CheckAccess 
public class MyWpfObject : DispatcherObject
{
    public void DoSomething()       
    {
        VerifyAccess();

        // Do some work
    }

    public void DoSomethingElse()
    {
        if (CheckAccess())
        {
            // Something, only if called 
            // on the right thread
        }
    }
}

Я не видел этого ни в одном из пользовательских элементов управления, с которыми я сталкивался (насколько я помню),

  • Используете ли вы это при создании пользовательских элементов управления?
  • Должно ли это делать или просто приятно иметь?
  • Кто-нибудь когда-либо сталкивался с какой-либо проблемой из-за ее отсутствия в вашем контроле?

1 Ответ

6 голосов
/ 06 сентября 2010

Нет, никогда не использовал это.И никогда не замечал, что кто-то использует его в контексте пользовательских элементов управления.Это правило также не соблюдается в WPF Toolkit.

Этот подход не только загрязняет код, но и делает ваш пользовательский элемент управления ответственным за то, о чем он не должен заботиться.Рассмотрим ситуацию, когда вы всегда делаете:

// Don't do this in all methods of your custom control!
public void Foo()
{
  if (!CheckAccess())
  {
    Dispatcher.Invoke(()=> Foo()); // Transit to UI Thread
    return;
  }
  // .. do work in UI.
}

На первый взгляд этот код выглядит хорошо.Если вы не в потоке пользовательского интерфейса, перейдите к потоку пользовательского интерфейса, выполните операцию и верните результат.Правильно?- НЕПРАВИЛЬНО!

Проблема 1. Когда вы вызываете Dispatcher.Invoke(), вы блокируете вызывающий поток, пока ваш запрос не будет обработан потоком пользовательского интерфейса.Это приводит к снижению производительности.Конечно, вы можете изменить это значение на Dispatcher.BeginInvoke(), теперь ваши клиенты должны знать, что их работа выполняется асинхронно.Т.е. если клиент пишет что-то для управления, а затем сразу же читает его обратно, нет гарантии, что операция уже выполнена потоком пользовательского интерфейса.

Проблема 2. Рассмотрим последующие вызовы метода Foo() из потока без пользовательского интерфейса.Например, он вызывается в цикле:

// Somewhere not in UI
for (int i = 0; i < 1000000; i++)
{
  control.Foo(); // Looks good, but performance is awful!
}

Вместо того, чтобы блокировать вызывающий поток 1000000 раз, разработчик мог бы реализовать одну проверку в вызывающем потоке и при необходимости перейти к пользовательскому интерфейсу, вместо того, чтобы неосознанно возвращаться назад и вычислять ценность между потоками.

Кроме того, WPF выполнит эту проверку для вас, когда вы получите доступ к элементу пользовательского интерфейса из потока, не являющегося пользовательским интерфейсом.Он кричит достаточно громко, чтобы сокрушить приложение и быть услышанным разработчиком, который сделал что-то не так:).

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...