Как я могу всегда ссылаться на мой метод ProgressForm.UPDATEME («новое сообщение прогресса») в любом другом методе в моем коде?
blockquote>Нравится это:
public void UPDATEME(string MSG, bool finish = false) { if (this.InvokeRequired) { this.Invoke(new MethodInvoker(() => this.UPDATEME(MSG, finish))); } else { this.label1.Text = MSG; if (finish) { this.Close(); } } }
Я действительно не понимаю, как вызов метода изнутри сам по себе оборачивается тем фактом, что метод вызывается за пределами потока первого уровня ...
blockquote>It сначала сбивает с толку, так как это рекурсивный вызов. «Мясо» - это то, что
Invoke()
запускает все, что находится внутри него, в том же потоке, который создал элемент управления (сама форма в этом случае). Когда мы вводим метод во второй раз (из-за рекурсии), проверка возвращает false, и мы безопасно запускаем блок else в потоке пользовательского интерфейса.Вы можете фактически избавиться от проверки (и рекурсии) всегда вызывая
Invoke()
, нужно ли это или нет:public void UPDATEME(string MSG, bool finish = false) { this.Invoke(new Action(() => { this.label1.Text = MSG; if (finish) { this.Close(); } })); }
Вот альтернативная версия, которая все еще проверяет, требуется ли
Invoke()
, но не использует рекурсию (менее запутанной, ve теперь вводил повторяющийся код):public void UPDATEME(string MSG, bool finish = false) { if (this.InvokeRequired) { this.Invoke(new Action(() => { this.label1.Text = MSG; if (finish) { this.Close(); } })); } else { this.label1.Text = MSG; if (finish) { this.Close(); } } }
Для тех, которые являются «ориентированными на детали», вот подход / вариация (я использую
MethodInvoker
вместоAction
), показывая один способ удалите дублирующий код выше:public void UPDATEME(string MSG, bool finish = false) { if (this.InvokeRequired) { this.Invoke((MethodInvoker)delegate { this.updater(MSG, finish); }); } else { this.updater(MSG, finish); } } private void updater(string MSG, bool finish = false) // NOT thread safe, thus the private (don't call directly) { this.label1.Text = MSG; if (finish) { this.Close(); } }