FAQ:WinAPI VCPP:прервать длительный процесс вычисления

Материал из Весельчак У
Версия от 20:14, 31 июля 2008; RXL (обсуждение | вклад) (Новая: ===У меня в программе имеется процедура, которая производит очень много вычислений. Как сделать так, чт...)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

У меня в программе имеется процедура, которая производит очень много вычислений. Как сделать так, чтобы пользователь мог прервать процесс вычислений?

1) В общем случае решение такое: вычисления производятся в одном потоке (T1) процесса, а обработка команд пользователя - в другом (T2). Одним из потоков может являться и основной поток. Поток T2, получив команду пользователя, выставляет определённый флаг (переменную, событие), доступный также и потоку T1. Поток T1, проверив флаг в определённый момент, прекращает/приостанавливает/продолжает свою работу. Естественно, скорость реакции T1 зависит от характера вычислений. Самый приятный вариант - вычисления, выполняемые в цикле, который часто повторяется. Тогда в начале или в конце цикла поток T1 просто проверяет флаг и принимает решение.

2) Есть ещё "ленивое решение" (подойдёт для простеньких приложений): вычисления выполняются в основном потоке, и также в начале цикла проверяется флаг. А кроме того, перед проверкой флага выполняется такой код:

// выполнить N сообщений из очереди сообщений
int imsg;
MSG m;
for (imsg = 0; imsg < N; imsg++)
{
	// выборка,выполнение и удаление одного сообщения
	// из очереди сообщений всех окон данного потока
	if (::PeekMessage(&m, 0, 0, 0, PM_REMOVE))
	{
		// транслирование виртуальных клавиш
		::TranslateMessage(&m);
		// обработка сообщения
		::DispatchMessage(&m);
	}
}

То есть будут обрабатываться все сообщения, в частности нажатия кнопок. Правда с тормозами. Тормоза можно попробовать регулировать числом N.

Примечание:

В любом случае необходимо тщательно продумать вариант, когда пользователь попытается закрыть программу во время вычислений. Самое простое: в главном окне программы перехватить WM_CLOSE и разрешить закрытие программы, либо вывести предупреждение и продолжить работу.