Я унаследовал некоторый код, который имеет два потока не-пользовательского интерфейса, которые обновляют различные элементы управления WinForm.
Код использует InvokeRequired и Invoke для обновления пользовательского интерфейса; однако время от времени я получаю сообщение об ошибке: Операция с несколькими потоками недопустима: доступ к элементу управления 'lvReports' осуществляется в потоке, отличном от того, в котором он был создан.
Я подозреваю, что имею дело с состоянием гонки и что мне нужно ввести блокировку в метод ниже, но, тем не менее, я могу найти десятки примеров того, как безопасно обновить пользовательский интерфейс из потока, не являющегося пользовательским интерфейсом, но примеров нет или обсуждение того, как работать с двумя потоками, обновляющими одинаковые элементы управления в сценарии гонки.
Итак, мой вопрос: как мне переписать приведенный ниже код для правильной обработки обновления пользовательского интерфейса с учетом состояния гонки и что мне нужно обновить пользовательский интерфейс из потоков, не относящихся к пользовательскому интерфейсу?
// two separate theads call this method in a instance of a WinForm
private void LoadReports()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(this.LoadReports));
}
else
{
// some code removed to keep exampe simple...
SetCtlVisible(lvReports, true);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate { lvReports.Refresh(); });
}
else
{
lvReports.Refresh();
}
}
}
delegate void SetVisibleCallback(Control ctl, bool visible);
private void SetCtlVisible(Control ctl, bool visible)
{
if (ctl.InvokeRequired)
{
SetVisibleCallback d = new SetVisibleCallback(SetCtlVisible);
ctl.Invoke(d, new object[] { ctl, visible });
}
else
{
ctl.Visible = visible;
}
}
Вот несколько мыслей:
Отличается ли this.InvokeRequired от ctl.InvokeRequired в любое время?
Нужен ли второй тест InvokeRequired с учетом первого?
Нужна ли реализация SetCtlVisible, если я оставлю первый InvokeRequired?
Должен ли я удалить первый InvokeRequired и оставить весь код в предложении else?
Требуется ли блокировка вокруг условия else?