Правильное использование (или отсутствие использования) Dispatcher.CheckAccess()

В Winforms все элементы управления имеют свойство InvokeRequired, которое возвращает true, если мне нужно позвонить. [Begin] Вызовите элемент управления, чтобы его изменить.

В WPF существует, по-видимому, аналогичная конструкция в DispatcherObject.CheckAccess() и Dispatcher.CheckAccess(), но меня испугает атрибут EditorBrowsable(EditorBrowsableState.Never). Когда я отключу просмотр редактора таким образом, я использую его, чтобы это означало: "Вы не должны этого делать. Нет, на самом деле. Если это необходимо, решите свою непосредственную проблему, вы неправильно разработали свое решение для своей всеобъемлющей проблемы". С другой стороны, единственная альтернатива, которую я нашел (и, фактически, мое оригинальное решение), - Thread.CurrentThread.ManagedThreadId == 1. (Это ужасно, но это не работает в общем случае. Я знаю, но это работает для моего ограниченного использования.)

MSDN документация умалчивает о наличие и обоснование атрибута EditorBrowsable. Разве это действительно означает "не использовать это", как если бы я набрал его, или у него есть какой-то другой менее запретительный смысл?

Ответ 1

В WPF вы можете вызывать Dispatcher.Invoke независимо от текущего потока, и он будет обрабатывать вызов соответственно - если вы уже находитесь в правильном потоке, он просто вызовет ваш код и использует CheckAccess для обработки этого поведения.

Для BeginInvoke поток, который вы сейчас используете, не имеет значения: BeginInvoke всегда асинхронный, а порядок выполнения зависит от приоритета элемента, добавляемого в очередь диспетчера.

Если вы вообще не должны использовать этот метод, он не будет общедоступным: цель этого атрибута состоит только в том, чтобы скрыть элемент от таких механизмов, как Intellisense и другие браузеры-редакторы. Обычно вам не нужно использовать Dispatcher.CheckAccess(), что, вероятно, означает, что оно помечено как недоступное для просмотра, но мудрость этого - это то, о чем мы можем только догадываться (если только Эрик Липперт не смотрит, -)

Вкратце: просто позвоните Dispatcher.Invoke и не беспокойтесь о CheckAccess.

Ответ 2

Я бы добавил: если вы хотите подражать "If invokeRequired then..."
Я бы сказал: не используйте "if Dispatcher.CheckAccess" Вместо этого используйте:

If Me.Dispatcher.Thread Is System.Threading.Thread.CurrentThread Then
    Label1.Content = value
Else
    Me.Dispatcher.BeginInvoke(New Action(Of String)(AddressOf displaymessage), value)
    Return
End If


Проблема была в том, что CheckAccess всегда был прав, даже ПОСЛЕ начала вызова...

Nevermind, следующий код также отлично работает:

   If Me.Dispatcher.CheckAccess Then
    Label1.Content = value 
  Else
    Me.Dispatcher.BeginInvoke(New Action(Of String)(AddressOf displaymessage), value)
    Return
End If