Пользовательский интерфейс-нить против фоновом потоке - элемент управления пользовательского интерфейса граница доступности


Вполне возможно, что на мой вопрос вообще нельзя ответить, и если да, то это интересная информация, несмотря ни на что. Я пытаюсь лучше понять взаимодействие элементов управления пользовательским интерфейсом, в частности, что разрешено и что не разрешено выполнять потоками, не являющимися потоками пользовательского интерфейса. В моем случае я взаимодействую как с элементами управления WPF, так и с объектами (которые представляют элементы управления), которые находятся в Microsoft.Офис.Пространства взаимодействия. Я делаю много работы с фоновыми потоками в слое модели, но когда события полученные в моем представлении-модели, я отправляю в поток пользовательского интерфейса (это обычно при работе со свойствами, которые привязаны к элементам управления WPF). Это имеет смысл для меня, и это, кажется, работает хорошо. Однако я не уверен, что может и не может быть сделано фоновыми потоками. По сути, я пытаюсь понять, где проходит граница. Чтобы развить воображение, смотрите некоторые вопросы ниже. Я понимаю, что мой запрос немного открыт, поэтому, если кто-то знает внешний ресурс, я могу прочитать это так же хорошо для меня.

  • могу ли я get() на свойство, связанное с ui из фонового потока, т. е. только set(), что должно быть сделано из потока UI?
  • Если у меня есть объект взаимодействия, скажем, Microsoft.Офис.Взаимодействие.Слайд, мне кажется, что я должен взаимодействовать с ним в потоке пользовательского интерфейса, потому что он должен быть реальным элементом управления пользовательского интерфейса. Но могу ли я слушать события, которые возвращают такие объекты в потоках, отличных от пользовательского интерфейса? Могу ли я проверить слайд на null из потока, не связанного с пользовательским интерфейсом? Могу ли я get() на свойства, содержащиеся в типе слайда из потока без пользовательского интерфейса?

Итак, есть ли хорошее правило, которое я могу иметь в виду при переключении между фоновыми потоками и потоком пользовательского интерфейса? Например, "любое действие, которое изменяет элемент управления пользовательского интерфейса, должно быть выполнено в потоке пользовательского интерфейса", или "любое действие, котороенепосредственно взаимодействует с , независимо от действия (например, проверка на null) с элементом управления пользовательского интерфейса, должно быть выполнено в потоке пользовательского интерфейса".

1 2

1 ответ:

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

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

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

То же самое относится и к результату потока, обычно нет смысла обновлять пользовательский интерфейс внутри потока. Классы BackgroundWorker и Task помогают запустить код в потоке пользовательского интерфейса после завершения потока, он может безопасно обновите пользовательский интерфейс с результатом. Позволяя нитям делать небольшие вещи, которые легко продумать и легко заблокировать, очень важно держаться подальше от неприятностей.

Office interop немного отличается от WPF, потокобезопасность в COM автоматическая. Он автоматически вызывает эквивалент диспетчера.Вызовите (), и никакая дополнительная помощь не требуется. И офисный документ, скорее всего, останется статичным, пока работает рабочий поток. За исключением тех случаев, когда вы позволяете пользователю также изменять документ, то у вас есть проблемы с добытчиком обратно в пик. YMMV.