C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Работа с потоками, Нужны советы
Schumi
Отправлено: 01.06.2005, 20:35


Машинист паровоза

Группа: Участник
Сообщений: 206



Я работаю в своей программе с потоком:
1) сперва создаю через CreateThread
2) в функции потока проверяю некоторую переменную, условно: ThreadTerminate. И если она true — выхожу. Ясно, что с учетом алгоритма работы, проверяется она не всегда, а через некоторый промежуток времени (идут некие фоновые расчеты).

Понятно, что возникают трудности, когда закрывается программа, а поток продолжает работать.
На данный момент, как я делаю: устанавливаю ThreadTerminate в true. После это в цикле (условно i=0...10) — проверяю GetExitThread (вроде так называется) smile.gif ,если еще активна, то делаю паузу в 200 мс и снова проверяю. Если закончилась работа, то CloseHandle.

Я догадываюсь, что есть более оптимальный вариант с прекращением работы процесса biggrin.gif . Посоветуйте.
Asher
Отправлено: 02.06.2005, 08:58


Мастер участка

Группа: Модератор
Сообщений: 550



Привет.
Логически все верно и ничего особо здесь не придумаешь.
Единственно что — так это лучше ограничивать время нахождения внутри твоих вычислений, чтобы за время ожидания завершения поток успел флаг проверить.
Ну и ждать завершения можно не циклом, а WaitForSingleObject(hThread, MyPause);
где MyPause — время которое ты согласен подождать завершения потока. У тебя это 2*100 мс.
Ну и хороший вариант — не грохать потоки просто так, а только при завершении программы. Если приходится пользоваться потоком несколько раз, то по завершении вычисления отправлять его в сон, по
WaitForSingleObject(hEvent, INFINITE);
и когда нужно снова посчитать — будить посылкой SetEvent(hEvent);
Ну и после выставления ThreadTerminate только неплохо бы поток будить. wink.gif
Тиграша
Отправлено: 03.06.2005, 05:31


Ученик-кочегар

Группа: Участник
Сообщений: 24



А мне вот тут помогли
Mark Cashman
Георгий
Отправлено: 03.06.2005, 10:07


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



QUOTE (Тиграша @ 03/06/2005, 06:31)
А мне вот тут помогли
Mark Cashman

у нас в "уроках" что-то похожее было, но на русском языке
Schumi
Отправлено: 03.06.2005, 20:35


Машинист паровоза

Группа: Участник
Сообщений: 206



Тогда хочется поставить вопрос ребром. Кратко суть проблемы: у меня есть некая таблица. Число строк очень велико, для каждой строки нужно вычислять значение (время вычисления — пару секунд). Если сразу считать значения всей таблицы, то уходит время — много ~1 мин.
Как я переделал: в событии OnDraw таблицы делаю так: если для данной строки еще значение не вычислено, то вычисляю, если вычислено, то беру и вывожу. Т.е получается, некоторый расчет на лету. С другой стороны — в фоновом режиме запускаю поток, который аналогично вычисляет значение всех еще не обработанных строк.
Обработка вычисляется посредством вызова функции (Func), условно — она принимает номер строки, и возвращает требуемое значение. Причем в ней проверяется — расчитано значение или нет.
Вы спросите — а зачем мучатся с потоком, если действительно, обрабатывать строки по мере надобности. Отвечу — помимо этого пользователю нужно подсчитывать некоторый критерий. Достоверность результата возможно лишь в случае обработки всех строк. Таким образом у меня постоянно в в Func выводится текущее значение критерия и % обработанных строк.
В принципе работает. Хотя иногда у label и progressbar, которые обновляются в Func меняется цвет smile.gif . Самое интересное, с таким успехом можно проблем не разгрести, учитывая, что в основной проге по событию OnDraw и в потоке вызывается одна и таже функция.
Ясно, что надо как-то контролировать работу этой функции, чтобы работал одновременно только один.
Я читал, что можно это делать через mutex, семафоры, timer и increment/decrement крученый. Я попробовал через CreateMutex — ReleaseMutex. Но учитываю, что не совсем разобрался (если не сказать больше biggrin.gif ).
Объясните, пожалуйста, кто знает, на пальцах, как это сделать. Или если у кого есть уже опыт, какими средствами лучше воспользоваться.
Schumi
Отправлено: 11.06.2005, 22:47


Машинист паровоза

Группа: Участник
Сообщений: 206



С этим разобрался. Но теперь другая проблема — я хочу в функции потока показать форму. То есть что-то далется, прогресс идет и в некоторый момент времени надо, чтобы появилась сообщение (реализовываю через форму).Испробовал разные варианты: создавал прямо в функции или уже была создана: при этом форма должна показываться не модально — и через ShowWindow и через Show. Все одно — оно появляется и тут же исчезает. В чем причина?
Konstantine
Отправлено: 13.06.2005, 09:29


Мастер участка

Группа: Модератор
Сообщений: 545



из потока с функциями VCL работать только через Sinhronize()
Schumi
Отправлено: 13.06.2005, 14:07


Машинист паровоза

Группа: Участник
Сообщений: 206



Мой опыт показывает, что не обязательно — многое получалось выполнять и из потока: устанавливать свойства, вызывать методы
Георгий
Отправлено: 13.06.2005, 15:02


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



QUOTE (Schumi @ 13/06/2005, 15:07)
Мой опыт показывает, что не обязательно — многое получалось выполнять и из потока: устанавливать свойства, вызывать методы

а вот этого не надо — ошибки из за повторной невходимости в функции гораздо страшнее и разрушительнее даже, чем промахи по памяти.
причём проявляются они гораздо реже, и зачастую с тестовой обвязкой не выявляются, а на объекте у заказчика вылазят.

лучше не надо — нервы дороже.

Вернуться в Вопросы программирования в C++Builder