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

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

Ответы [ 4 ]

10 голосов
/ 16 октября 2008

Существует общее правило, согласно которому не обновляйте пользовательский интерфейс из какого-либо потока, кроме самого потока пользовательского интерфейса. Использование функций 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."});

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

5 голосов
/ 16 октября 2008

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

ссылка на подробности

1 голос
/ 16 октября 2008

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

if (InvokeRequired)
        {
            //This.Invoke added to circumvent cross threading exceptions.
            this.Invoke(new UpdateProgressBarHandler(UpdateProgressBar), new object[] { progressPercentage });
        }
        else
        {
            UpdateProgressBar(progressPercentage);
        }
1 голос
/ 16 октября 2008

Здесь обсуждается здесь и один здесь .

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

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...