Каков наилучший способ обновить элементы управления формой из рабочего потока?

StackOverflow https://stackoverflow.com/questions/206867

  •  03-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

Существует общее эмпирическое правило, которое гласит, что не обновляйте пользовательский интерфейс ни из какого потока, кроме самого потока пользовательского интерфейса.Использование функций BackgroundWorker - хорошая идея, но вы этого не хотите, и что-то происходит в другом потоке, вы должны выполнить "Invoke" или BeginInvoke, чтобы заставить делегата выполнить метод в потоке пользовательского интерфейса.

Редактировать:Джон Би сделал это хорошее замечание в комментариях:

Имейте в виду, что Invoke() является синхронным, а BeginInvoke() - асинхронным.Если вы используете Invoke(), вы должны быть осторожны, чтобы не вызвать взаимоблокировку.Я бы рекомендовал BeginInvoke(), если вам действительно не нужно вызов должен быть синхронным.

Несколько простых примеров кода:

// Updates the textbox text.
private void UpdateText(string text)
{
  // Set the textbox text.
  m_TextBox.Text = text;
}

public delegate void UpdateTextCallback(string text);

// Then from your thread you can call this...
m_TextBox.Invoke(new UpdateTextCallback(this.UpdateText),
    new object[]{"Text generated on non-UI thread."});

Приведенный выше код взят из часто задаваемых вопросов по этому поводу здесь и более длительный и запутанный здесь.

Другие советы

Почему вы не хотите сделать это с помощью BackgroundWorker?У него есть фантастическое событие обратного вызова под названием ProgressChanged, которое позволяет потоку пользовательского интерфейса узнавать об обновлениях, идеально подходит для обновлений типа progress bar и тому подобного.

ссылка на подробную информацию

Есть дискуссия, связанная с этим здесь и один здесь.

По сути, вы используете Invoke для достижения этой цели.

Желаю удачи!

Я бы также рассмотрел InvokeRequired (только VS2008) при вызове Invoke .Бывают случаи, когда вы не будете обновлять пользовательский интерфейс из отдельного потока.Это экономит накладные расходы на создание делегата и т.д.

if (InvokeRequired)
        {
            //This.Invoke added to circumvent cross threading exceptions.
            this.Invoke(new UpdateProgressBarHandler(UpdateProgressBar), new object[] { progressPercentage });
        }
        else
        {
            UpdateProgressBar(progressPercentage);
        }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top