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

Вот проблема, которая у меня есть: мне нужно убедиться, что объект создается в потоке пользовательского интерфейса. Если это не так, он должен генерировать исключение. Но как проверить внутри метода, работает ли он в потоке пользовательского интерфейса? Примечание. Я не хочу передавать какую-либо информацию в конструктор объекта.

Идеальным кандидатом был бы DispatcherSynchronizationContext (реализация SynchronizationContext в WPF), который внутренне содержит ссылку на Dispatcher, которая ссылается на поток, с которым он связан, но, к сожалению, это поле является закрытым, поэтому у меня нет возможности получить к нему доступ.


person Community    schedule 25.05.2009    source источник


Ответы (2)


Небольшое уточнение: хотя обычно существует только один поток пользовательского интерфейса, потоков пользовательского интерфейса может быть много. Это справедливо как для WPF, так и для WinForms.

Лучший способ, который я нашел для достижения этого, - это SynchronizationContext. И WPF, и WinForms установят SynchronizationContext в любом потоке, в котором они запускают пользовательский интерфейс. Это функция, которую я использую, если я не привязан к какой-либо конкретной модели пользовательского интерфейса.

public bool IsPossiblyUIThread() {
  return SynchronizationContext.Current != null;
}

Обратите внимание, что это никоим образом не является надежным. Компоненты, не связанные с пользовательским интерфейсом, могут установить SynchronizationContext, и это вернет true для простого рабочего потока. Отсюда и неавторитетное название.

Ниже приведен немного более надежный способ сделать это. Но это требует, чтобы вы ссылались хотя бы на часть WPF для реализации.

public bool IsLikelyWpfUIThread() {
  var context = SynchronizationContext.Current;
  return context != null && context is DispatcherSynchronizationContext;
}
person JaredPar    schedule 25.05.2009
comment
Да, это, кажется, лучший способ. Огромное спасибо! - person ; 25.05.2009

Dispatcher.CheckAccess() возвращает true, если ваш код выполняется в том же потоке, что и Dispatcher. Это должно работать, если есть только один Dispatcher/UIThread.

person Nick    schedule 25.05.2009
comment
Это может быть правдой, но учтите, что Dispatcher всегда связан с потоком, в котором он был создан. Таким образом, использование Dispatcher.CheckAccess() мало чем поможет, если объект был создан в другом потоке. - person ; 25.05.2009