Что не так с вызовом Invoke, независимо от InvokeRequired? - PullRequest
38 голосов
/ 14 апреля 2009

Я видел общие настройки для многопоточного доступа к элементу управления с графическим интерфейсом, как обсуждалось здесь: Кратчайший способ написать потокобезопасный метод доступа к элементу управления Windows Form

Все найденные мной веб-хиты описывают похожую вещь.

Однако зачем нам проверять InvokeRequired? Разве мы не можем просто позвонить в Invoke напрямую?

Я предполагаю, что ответ - нет, поэтому мой настоящий вопрос - "почему"?

Ответы [ 6 ]

30 голосов
/ 14 апреля 2009

Из потоков, не относящихся к пользовательскому интерфейсу, мы не можем касаться пользовательского интерфейса - могут случиться очень плохие вещи, поскольку элементы управления имеют сходство потоков. Так что из потока, не являющегося пользовательским интерфейсом, мы должны (как минимум) вызвать Invoke или BeginInvoke.

Для UI-потоков, однако - мы не хотим вызвать Invoke много времени; проблема заключается в том, что если вы уже уже находитесь в потоке пользовательского интерфейса, у него все еще есть ненужные накладные расходы на отправку сообщения в насос формы и его обработку.

В действительности, в большинстве потоковых кодов, которые вы знаете , вы ожидаете вызова определенного метода в потоке не -UI, поэтому в этих случаях нет дополнительных затрат: просто позвоните Invoke.

3 голосов
/ 14 апреля 2009

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

1 голос
/ 18 апреля 2012

Если вы попытаетесь вызвать до создания дескриптора окна (например, при вызове конструктора формы), вы получите InvalidOperationException. Итак, обычно InvokeRequired проверка требуется.

Подробнее см. MSDN .

1 голос
/ 14 апреля 2009

Проблема заключается в том, что для элементов управления GUI требуется, чтобы только код, выполняющийся в том же потоке, который использовался для создания экземпляра элемента управления GUI, мог получить доступ к элементу управления GUI. Причины этого требования связаны с тем, как Windows спроектирована. Достаточно сказать, что это было бы очень трудно изменить.

InvokeRequired проверяет идентичность текущего исполняющего потока и идентичность создаваемого потока. Если они одинаковы, код может свободно взаимодействовать с элементом управления. Если нет, код должен перенаправить данные из текущего потока в поток создания экземпляра. Это медленный и дорогостоящий процесс, и его следует избегать, если это вообще возможно. Ваш код будет работать, если вы всегда вызываете, и может случиться так, что вы не заметите снижения производительности, но этот сценарий будет становиться все более распространенным по мере использования многоядерных систем. Лучше всего не создавать кодовые «узлы», которые необходимо отменить позже.

0 голосов
/ 14 апреля 2009

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

0 голосов
/ 14 апреля 2009

Invoke собирается вызывать код через Delegate, а не напрямую, что будет дорогостоящим.

Экономически выгодно вызывать Invoke только тогда, когда это требуется. Следовательно, InvokeRequired используется для выяснения, выполняется ли вызов из того же потока или другого потока?

...