Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Многопоточность.doc
Скачиваний:
4
Добавлен:
28.10.2018
Размер:
225.79 Кб
Скачать

Класс BackgroundWorker

Последним способом взаимодействия пользовательского интерфейса и отдельного потока, о котором я хочу рассказать, является использование класса BackgroundWorker. Это компонент, который можно поместить на форму, перетащив мышкой из палитры компонентов. Какие же возможности он нам предоставляет?

Основным для класса BackgroundWorker является событие DoWork. Обработчик этого события вы пишете сами, именно он будет исполняться в отдельном потоке. Запуск отдельного потока осуществляется вызовом метода RunWorkerAsync экземпляра класса BackgroundWorker. Этому методу можно передать параметр типа object, в который можно упаковать любые данные, необходимые вашему потоку:

long checkNumber = GetCheckNumber();

backgroundWorker.RunWorkerAsync(checkNumber);

В вашем обработчике события DoWork эти данные доступны через свойство Argument параметра типа DoWorkEventArgs:

long checkNumber = (long) e.Argument;

Окончание работы и возвращение результата

Если ваш метод, выполняющийся в отдельном потоке, должен возвращать какой-то результат, присвойте этот результат свойству Result объекта DoWorkEventArgs. Тогда он будет доступен после завершения работы вашего метода. Об окончании его работы уведомляет событие RunWorkerCompleted класса BackgroundWorker:

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

{

pb.Minimum = 0;

pb.Maximum = 100;

pb.Value = 0;

btnCheck.Enabled = true;

if (e.Error != null)

{

MessageBox.Show(this, e.Error.Message, "Ошибка");

return;

}

if (e.Cancelled)

{

MessageBox.Show(this, "Пользователь отменил выполнение метода.", "Информация");

return;

}

bool isPrime = (bool) e.Result;

if (isPrime)

{

MessageBox.Show(this,

"Число является простым.",

"Информация");

}

else

{

MessageBox.Show(this,

"Число не является простым.",

"Информация");

}

}

Достоинство этого метода в том, что он выполняется в потоке пользовательского интерфейса, поэтому вам нет нужды заботиться о синхронизации. Данному методу передается параметр типа RunWorkerCompletedEventArgs, который имеет следующие полезные свойства:

  1. Если в вашем потоке произошло необработанное исключение, вы можете получить его с помощью свойства Error. Более того, вы обязаны сделать это, поскольку обращение к любым другим свойствам объекта RunWorkerCompletedEventArgs вызовет генерацию исключения.

  2. Если пользователь прервал работу вашего метода (об этом позже), вы мощете узнать об этом из свойства Cancelled.

  3. Наконец, вы можете получить результат работы вашего метода через свойство Result.

Прогресс выполнения

Вывод на экран прогресса выполнения длительной операции является стандартной задачей. Класс BackgroundWorker для этих целей имеет метод ReportProgress. Ему передается целое число, которое указывает процент выполненой работы.

backgroundWorker.ReportProgress((int)(100.0 * 2 * d / checkNumber));

Этот метод приводит к вызову события ProgressChanged, обработчик которого вы можете написать самостоятельно:

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)

{

pb.Value = e.ProgressPercentage;

}

В данном обработчике вы можете получить переданный процент с помощью свойства ProgressPercentage класса ProgressChangedEventArgs. Этот метод так же выполняется в потоке пользовательского интерфейса, так что вы можете не использовать Invoke.