2

Я использую это, чтобы обновить элемент управления в главном потоке из другого потока:управления Обновление в главном потоке, используя EventHandler

private void ShowHourGlassSafe(bool visible) 
{ 
    this.Invoke((EventHandler)((s, ev) => pictureBoxHourGlass.Visible = visible));   
} 

Интересно, каковы последствия делают это таким образом, или если есть какие-либо риск, что это провалится?

Из многих примеров можно найти то же самое, что я не мог найти такого.

Возможно, это просто неправильно?

ответ

2

Типичные проблемы с таким кодом:

  • Вы тупиковые, если поток UI делает что-то неразумно, как в ожидании потока, чтобы закончить. Нет смысла использовать Invoke, который блокирует рабочий поток без каких-либо преимуществ, просто используйте BeginInvoke. Решает тупиковый потенциал и ненужную задержку.

  • Вы столкнетесь, когда пользовательский интерфейс будет закрыт, и будет выставлен pictureBoxHourGlass. Упрощение того, что поток больше не работает, прежде чем разрешить закрытие пользовательского интерфейса, очень часто игнорируется. Просто показывать часовое стекло недостаточно, вам также нужно принять контрмеры, чтобы пользователь не закрывал пользовательский интерфейс. Или иначе заблокируйте его, чтобы сначала отменить нить.

  • Пользователь, как правило, путается, когда появляется часовое стекло, если он ничего не сделает, чтобы попросить что-то сделать. Правильный случай на 99% состоит в том, что вы показываете часовое стекло с кодом в потоке пользовательского интерфейса, а затем начинаете поток. И спрячьте его снова, когда поток завершится. Проще всего сделать с классами BackgroundWorker или Task, они могут запускать код в потоке пользовательского интерфейса после выполнения задания.

Фавор типы действий делегат совместности:

private void ShowHourGlassSafe(bool visible) { 
     this.BeginInvoke(new Action(() => something.Visible = visible)); 
    } 
+0

К вашему первому пункту вы будете только тупиком, если что-то, что блокирует поток пользовательского интерфейса, ждет в фоновом потоке. Если нет, вы просто блокируете какое-то время, не зацикливая *. – Servy

+0

Кроме того, я помню, что он заметил, что «Control.Invoke» оптимизирован для нескольких конкретных делегатов, из которых «Action» не является одним из них, что не позволяет использовать его для всех вызовов Invoke. – Servy

+0

Мне пришлось изменить его на this.BeginInvoke (новое действие ((o) => pictureBoxHourGlass.Visible = visible)); Поскольку я использую CF 2.0, я не уверен, но я прочитал, что для использования BeginInvoke я должен проверить, требуется ли сначала invoke? или он должен работать так, как есть? спасибо – montelof

3

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

private void ShowHourGlassSafe(bool visible) 
{ 
    this.Invoke((MethodInvoker)(() => pictureBoxHourGlass.Visible = visible));   
} 

Кроме этого, основная концепция того, что вы делаете, это прекрасно.

+0

Спасибо, к сожалению, я не могу использовать MethodInvoker в CF 2.0. но Im рад, что ничего другого помимо дополнительных параметров не так. – montelof

 Смежные вопросы

  • Нет связанных вопросов^_^