Подтвердить что ты не робот

Не слепо использовать InvokeRequired только плохую практику?

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

На самом деле это вопрос из этого вопроса.

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

В теории я согласен, что это может сэкономить некоторое время. После некоторых тестов выяснилось, что использование Invoke занимает примерно в два раза больше времени, чем обычно вызов операции (тесты, такие как установка текста метки n раз или размещение очень большой строки в RichTextBox).

Но! Тогда есть практика.

Документация MSDN гласит:

Это свойство может использоваться для определения необходимости вызова метода invoke, который может быть полезен, если вы не знаете, какой поток принадлежит элементу управления.

В большинстве случаев вы do знаете, когда пытаетесь получить доступ к элементу управления из другого потока. На самом деле единственная ситуация, о которой я могу думать, - это доступ к элементу управления из метода, который может быть вызван потоком X, а также потоком владельца. И это для меня очень маловероятная ситуация.

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

Итак, если я правильно понимаю, единственный сценарий, когда вам нужно проверить, требуется ли вызов, - это когда вы не знаете, какой поток обращается к элементу управления, и когда обновление GUI занимает более 40 мс.

Тогда есть ответ на этот вопрос, который я задал http://programmers.stackexchange.com. В котором говорится, что вы не должны быть заняты преждевременной оптимизацией, когда вам это не нужно. Особенно, если он жертвует удобочитаемостью кода.

Итак, это подводит меня к моему вопросу: не следует ли вам просто использовать invoke, когда вы знаете, что другой поток обращается к элементу управления, и только, когда вы знаете, что ваш поток пользовательского интерфейса может получить доступ к этому фрагменту кода и, вы обнаружите, что он должен работать быстрее, чтобы проверить, требуется ли Invoke?

PS: после проверки моего вопроса это действительно звучит так, как будто я разглагольствовал. Но на самом деле мне просто интересно, почему InvokeRequired, по-видимому, чрезмерно используется многими более опытными программистами.

4b9b3361

Ответ 1

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

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

С другой стороны, если вызов всегда возникает из потока, отличного от потока пользовательского интерфейса, просто используйте Invoke, не проверяя сначала InvokeRequired.

Это приводит к трем простым правилам:

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

Ответ 2

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

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

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