Программирование на Visual C++. Архив рассылки | страница 17



A3. Самый оптимальный по-моему способ: Это запустить worker thread – второй поток (если пока только один :)) ) апликации. В качестве параметра передать туда структуру с необходимыми данными, а можно и ничего не передавать. Если все данные хранятся в наследнике CWinApp (дальше – CMyApp) , то получить доступ к объекту апликации можно с помощью функции AfxGetApp(). Единственное замечание по передаче данных из одного потока в другой заключается в том, что надо доступаться ТОЛЬКО к мемберам класса – нельзя вызывать функции класса из другого потока (вернее, можно, если они не изменяют данных класса или не обращаются к оконным функциям класса (относиться к наследникам CWnd)). В итоге имеем схему: 

1. Создается worker thread (поток одной функции, при ее завершении завершается и поток). В качестве параметра функции AfxBeginThread передается указатель на необходимые данные.

2. В основном потоке создается собственное сообщение, сигнализирующее о завершении потока. Оно будет брошено рабочим потоком перед своим завершением с помощью PostMessage (при работе с потоками я предпочитаю PostMessage для обмена такого рода сообщениями, ведь SendMessage ждет завершения работы обработчика события, что часто просто не нужно).

3. Запущенный поток выполняет всю черновую работу, в то время как основной поток апликации занимается важными делами, а именно – ничего не делает, знай крутит себе цикл обработки сообщений и не жужжит.

4. По завершении работы, worker thread посылает основному потоку мессагу, мол я закончил, выкладывает результаты так, чтобы основной знал где они (как это сделать – миллионы способов :)), в частности, передать в завершающем сообщении указатель на данные результата. )

Примерный код таков.

>UINT WorkerThreadFunction(WPARAM, LPARAM lpData) {

> // тутачки работаем с lpData и выполняем

> // всю необходимую работу

> // результат запихиваем в память,

> // а адрес на нее – в lpResult

> AfxGetMainWnd()->PostMessage(IID_WORKER_THREAD_END, 0, lpResult);

> // возвращаем код успеха (а вообще это на ваш вкус)

> return 0;

>}


>void CMyApp::OnStartExecution() {

> // заполняем lpData нужными данными, и вызываем ..

> CWinThread *pThread = AfxBeginThread(WorkerThreadFunction, lpData);

> if (!pThread) {

>  // Не смогли запустить поток.

>  // Правда обычно этот код не выполняется :)).

>  // Я до сих пор не знаю ситуации, когда поток

>  // может не запуститься, кроме low memory.

>  AfxMessageBox(_T("Can't start thread."));

> }