Программирование на 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."));
> }