Правильное использование (или отсутствие использования) 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