Главная arrow Программирование arrow PC arrow Visual Studio C++ 2010 Express: BackgroundWorker Class Saturday, November 25 2017  
ГлавнаяКонтактыАдминистрированиеПрограммированиеСсылки
UK-flag-ico.png English Version
GERMAN-flag-ico.png Die deutsche Version
map.gif карта сайта
нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Поделиться:

Visual Studio C++ 2010 Express: BackgroundWorker Class Версия для печати
Написал microsin   
16.11.2011

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

BackgroundWorker-class.PNG

Цикл потока BackgroundWorker запускается в обработчике события DoWork, (OnDoWork). Внимание: из этого обработчика нельзя менять пользовательский интерфейс, иначе возникнет конфликт с основным потоком программмы! Общение с пользовательским интерфейсом внутри потока DoWork возможно только через вызовы метода ReportProgress, что генерирует события ProgressChanged, которые можно обработать в потоке класса формы (свойство WorkerReportsProgress должно быть установлено при этом в true). Как начать работать с BackgroundWorker:

1. Бросаем на форму компонент BackgroundWorker (BackgroundWorker1).

2. В Form1_Load инициализируем BackgroundWorker:

//разрешение срабатывания событий ProgressChanged
BackgroundWorker1->WorkerReportsProgress = true;
//запуск тела DoWork
BackgroundWorker1->RunWorkerAsync();

3. Заходим в события BackgroundWorker1, и добавляем обработчики DoWork, ProgressChanged, RunWorkerCompleted.

4. Пишем в теле DoWork алгоритм работы BackgroundWorker наподобие следующего:

//////////////////////////////////////////////////////////////////////////////////
// Построение списка имеющихся портов
private: System::Void BackgroundWorker1_DoWork
                      (System::Object^ sender,
                       System::ComponentModel::DoWorkEventArgs^ e)
{
  BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);
  applog->Write("backgroundWorker DoWork");
  for(int i=1;i<100;++i)
  {
     sprintf_s(h411->CommName, COMM_NAME_LEN, "COM%d", i);
     if(h411->comport->Open(i,9600))
         worker->ReportProgress(i);
     h411->comport->Close();
  }
}

Здесь вызовы ReportProgress будут генерить события прогресса ProgressChanged.

5. Пишем тело обработчика события ProgressChanged наподобие такого:

//////////////////////////////////////////////////////////////////////////////////
// Обработчик события изменения статуса поиска портов
private: System::Void BackgroundWorker1_Changed
               (System::Object^ sender,
                System::ComponentModel::ProgressChangedEventArgs^ e)
{
  toolStripProgressBar1->Value = e->ProgressPercentage;
}

Здесь e->ProgressPercentage получает значение переменной i, через которую вызовом ReportProgress было передано значение прогресса.

6. Можно останавливать BackgroundWorker, если вызвать его метод CancelAsync():

BackgroundWorker1->CancelAsync();

Чтобы остановка сработала, нужно чтобы свойство WorkerSupportsCancellation было установлено в true. Кроме того, в теле цикла DoWork экземпляра BackgroundWorker нужно организовать проверку свойства CancellationPending, и если оно true, то прерывать выполнение цикла. Пример:

private: System::Void BackgroundWorker1_DoWork
                     (System::Object^ sender,
                      System::ComponentModel::DoWorkEventArgs^ e)
{
  BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);
  applog->Write("bBackgroundWorker1_DoWork START");
  for(idxOper=0; idxOper < dataGridView1->RowCount; idxOper++)
  {
     if (worker->CancellationPending)
         break;
     worker->ReportProgress(idxOper*100 / dataGridView1->RowCount);
     Sleep(200);
  }
  applog->Write("BackgroundWorker1_DoWork EXIT");
}

7. При завершении работы BackgroundWorker будет автоматически срабатывать событие RunWorkerCompleted. Оно срабатывает и при вызове CancelAsync(), если обработчик DoWork был завершен. Пример обработчика события завершения:

private: System::Void BackgroundWorker1_RunWorkerCompleted
                    (System::Object^ sender,
                     System::ComponentModel::RunWorkerCompletedEventArgs^ e)
{
  applog->Write("bwIterateCalibr_RunWorkerCompleted");
}

 

Последнее обновление ( 16.11.2011 )
 

Добавить комментарий

:D:lol::-);-)8):-|:-*:oops::sad::cry::o:-?:-x:eek::zzz:P:roll::sigh:

Защитный код
Обновить

След. >

Top of Page
 
microsin © 2017