Что плохого в вызове Invoke, независимо от InvokeRequired?
Я видел общую настройку для перекрестного потокового доступа к элементу управления GUI, как описано здесь: кратчайший способ записи потокобезопасного метода доступа к элементу управления windows forms
Все веб-хиты, которые я нашел, описывают одно и то же.
Однако, почему мы должны проверять InvokeRequired? Разве мы не можем просто вызвать Invoke напрямую?
Я предполагаю, что ответ-нет, поэтому мой настоящий вопрос- "почему"?
6 ответов:
Из не-UI потоков мы не можем коснуться UI - очень плохие вещи могут произойти, так как элементы управления имеют сходство с потоком. Поэтому из потока, не являющегося UI, мы должны (в минимуме) вызвать
Invoke
илиBeginInvoke
.Для потоков пользовательского интерфейса, однако-мы не хотим вызывать
Invoke
много времени; проблема в том, что если вы уже находитесь в потоке пользовательского интерфейса, он все еще имеет ненужные накладные расходы на отправку сообщения в насос формы и его обработку.На самом деле, в большинстве потоковых кодов вы знайте вы ожидаете, что конкретный метод будет вызван в потоке не-UI, поэтому в этих случаях нет никаких дополнительных накладных расходов: просто вызовите
Invoke
.
InvokeRequired
в основном говорит вам, если вы выполняете на правильном потоке или нет. Если вы не на правильном потоке, вам нужно маршалировать задачу на правильный поток, в противном случае вы этого не сделаете.
Проблема заключается в том, что элементы управления GUI требуют, чтобы только код, выполняемый в том же потоке, который использовался для создания экземпляра элемента управления GUI, мог получить доступ к элементу управления GUI. Причины этого требования связаны с тем, как устроена архитектура Windows. Достаточно сказать, что изменить это было бы очень трудно.
InvokeRequired проверяет идентичность текущего выполняющегося потока с идентичностью создаваемого потока. Если они одинаковы, то код может свободно взаимодействуйте с управлением. Если нет, то код должен маршалировать данные от текущего потока к потоку создания экземпляра. Это медленный и дорогостоящий процесс, и его следует избегать, если это вообще возможно. Ваш код будет работать, если вы всегда вызываете, и может оказаться, что вы не заметите снижения производительности, но этот сценарий будет все более распространенным, когда многоядерные системы войдут в употребление. Лучше всего не создавать кодовые "узлы", которые потом придется развязывать.
Если вы попытаетесь вызвать до того, как дескриптор окна будет создан (например, при вызове конструктора формы), вы получите
InvalidOperationException
. Итак, в общем случае требуется проверкаInvokeRequired
.СмотритеMSDN для получения подробной информации.