|
Zor
Глобальный модератор
Сказали спасибо: +158/-30
Offline
Сообщений: 2946
|
|
« : 28 Март 2008, 01:34:10 »
|
|
Ситуация:
Создаю пачку размороженых ниток (TThread[], CreateSuspended = false)
// код потока должен выполнить инит и остановится: Execute() { // init ... while (!Terminated) { Suspended = true; // (point:A) // something ... } // done ... } // после создания жду пока все добегут до состояния "заморожено" (или Terminated если облом): while (1) { if (Threads[]->Terminated || Threads[]->Suspended) break; }
Так вот, проблема в том, что иногда один-два потока (чаще один) где то застревает, никогда не доходя до (point:A)
WTF? И еще - отладчиком BC6 можно ходить по коду в потоках (F7/F8)?
|
|
| « Последнее редактирование: 19 Октябрь 2011, 14:12:00 от volvo877 » |
Записан |
|
|
|
|
OVE
Участник
Сказали спасибо: +67/-0
Offline
Сообщений: 72
|
|
« Ответ #1 : 28 Март 2008, 08:33:13 »
|
|
Попробуйте
while (1) { Application->ProcessMessages(); if (Threads[]->Terminated || Threads[]->Suspended) break; }
|
|
| « Последнее редактирование: 19 Октябрь 2011, 14:12:17 от volvo877 » |
Записан |
|
|
|
|
serg76
Участник
Сказали спасибо: +38/-2
Offline
Сообщений: 575
|
|
« Ответ #2 : 28 Март 2008, 09:21:53 »
|
|
Создаю пачку размороженых ниток (TThread[], CreateSuspended = false)
можно выложить пример, как создавать потоки в цикле
например for(int i=0;i<7;i++)
|
|
|
|
|
|
bred
А моск есть?
Участник
Сказали спасибо: +6/-0
Offline
Сообщений: 387
Нет - это фантастика!
|
|
« Ответ #3 : 28 Март 2008, 10:03:39 »
|
|
И еще - отладчиком BC6 можно ходить по коду в потоках (F7/F8)?
В принципе можно, но во-первых нет никакой гарантии что последовательность переключений между потоками будет производится как бы она производилась в нормальном режиме (да и вообще нет гарантии что она вообще будет производится;) ), а во-вторых по большей части такая отладка заканчивается в лучшем случае повисанием ПК с попытками вырубания билдера, захватившего все ресурсы, в течении минут 10 (у меня диспетчер задач однажды убивал билдер порядка 20-30 минут), либо просто перезагрузкой от кнопки "ресет". Кстати перезагружать машину после такой отладки (даже если все вроде прошло чудесно) все равно скорее всего придется .
|
|
|
|
|
|
Doga
Давний друг
Сказали спасибо: +31/-1
Offline
Сообщений: 241
|
|
« Ответ #4 : 28 Март 2008, 14:40:35 »
|
|
Привет.
Когда поток замораживается, система просто перестаёт выделять ему процессорное время. Возможно, причина в этом. Попробуйте использовать вместо Suspended какой-либо другой дополнительный флаг для проверки состояния потока.
Если у потока FreeOnTerminate = true, то в случае коректоной обработки флага Terminated, поток может самостоятельно завершить свою работу. Возможно, что Вы пытаетесь обратиться к уже не существующему потоку. Понятно, что последствия, в данном случае, не предсказуемы...
|
|
|
|
|
|
Zor
Глобальный модератор
Сказали спасибо: +158/-30
Offline
Сообщений: 2946
|
|
« Ответ #5 : 28 Март 2008, 14:43:49 »
|
|
2 OVE я обычно ставлю Sleep() вместо ProcessMessages(). Хотя это мысль - надо исходники порыть...
2 serg76 также как и прочие объекты:
for (int i = 0; i < 7; i++) Threads = new (nothrow) TMyThread(false);
|
|
|
|
|
|
Zor
Глобальный модератор
Сказали спасибо: +158/-30
Offline
Сообщений: 2946
|
|
« Ответ #6 : 28 Март 2008, 14:49:24 »
|
|
2 Doga ну уж если Suspended криво работает - можно сразу на апи переходить. FrеeOnTerminate не используется - надо же узнать почему поток незапланировано вылетел.
|
|
|
|
|
|
Doga
Давний друг
Сказали спасибо: +31/-1
Offline
Сообщений: 241
|
|
« Ответ #7 : 28 Март 2008, 15:12:13 »
|
|
Я не говорил, что Suspended криво работает.
Приведённый Вами код слишком сильно сокращён и не позволят представить полную картину происходящего в потоке. Давайте больше кода
Цель заморозки потоков не понятна. Зачем ожидать заморозки потоков или их завершения сразу после их создания? Не проще ли тогда создать их замороженными?
|
|
|
|
|
|
Asher
Администратор
Сказали спасибо: +111/-5
Offline
Сообщений: 425
|
|
« Ответ #8 : 28 Март 2008, 16:29:34 »
|
|
Привет всем.
Sleep на ожидание отработки может не помочь, с ProcessMessage уже лучше.
Я в таком случае делал цикл ожидания, внутри которого ProcessMessage() и ::SwitchToThread();
|
|
|
|
|
|
serg76
Участник
Сказали спасибо: +38/-2
Offline
Сообщений: 575
|
|
« Ответ #9 : 28 Март 2008, 16:44:02 »
|
|
for (int i = 0; i < 7; i++) Threads = new (nothrow) TMyThread(false);
эт наверно для тех, кто знал и подзабыл
и что надо для "nothrow" подключить ?
у меня Undefined symbol
|
|
|
|
|
|
Zor
Глобальный модератор
Сказали спасибо: +158/-30
Offline
Сообщений: 2946
|
|
« Ответ #10 : 28 Март 2008, 20:35:12 »
|
|
2 serg76 // Threads [ i ] = new ... , ачипятка
2 Asher проверил - никакой принципиальной разницы между Sleep и ProcessMessages тут нет. Дело вкуса. Разве что без тормоза Sleep лог успевает вырасти в разы больше
*********************************
Всем спасибо разобрался. Дело оказалось во врожденной глючности TThread.
оригинал статьи, если кому интересно: http://delphi.newswhat.com/geoxml/forumhistorythread?groupname=borland.public.delphi.nativeapi.win32&messageid=473950eb@newsgroups.borland.com
А вот виновник торжества:
procedure TThread.Resume; var SuspendCount: Integer; begin SuspendCount := ResumeThread(FHandle); <<<< вот здесь система переключает поток, и если он успевает дойти до Suspend() <<<< флаги состояния показывают фигню. CheckThreadError(SuspendCount >= 0); if SuspendCount = 1 then FSuspended := False; end;
напоминает новую реинкарнацию DivideByZero/RunTimeError200, правда?
|
|
| « Последнее редактирование: 19 Октябрь 2011, 14:12:36 от volvo877 » |
Записан |
|
|
|
|
serg76
Участник
Сказали спасибо: +38/-2
Offline
Сообщений: 575
|
|
« Ответ #11 : 09 Апрель 2008, 11:26:14 »
|
|
Вопрос в тему
несколько потоков используют одну ф-ю заполнения listbox
необходимо использовать Критический раздел или достаточно вызывать по Synchronize ?
|
|
|
|
|
|
bred
А моск есть?
Участник
Сказали спасибо: +6/-0
Offline
Сообщений: 387
Нет - это фантастика!
|
|
« Ответ #12 : 09 Апрель 2008, 12:51:29 »
|
|
по идее синхронайза должно хватить.
|
|
|
|
|
|
serg76
Участник
Сказали спасибо: +38/-2
Offline
Сообщений: 575
|
|
« Ответ #13 : 09 Апрель 2008, 16:04:54 »
|
|
в .h файле mytrd *mtr;
в .cpp
for (i = 0; i < 7; i++) mtr[i]= new (nothrow) mytrd(true);
выдает ошибку: VCL style classes must be constructed using operator new
оператор new есть, что не так
|
|
|
|
|
|
Zor
Глобальный модератор
Сказали спасибо: +158/-30
Offline
Сообщений: 2946
|
|
« Ответ #14 : 09 Апрель 2008, 20:44:46 »
|
|
а целиком?
|
|
|
|
|
|
serg76
Участник
Сказали спасибо: +38/-2
Offline
Сообщений: 575
|
|
« Ответ #15 : 10 Апрель 2008, 09:31:31 »
|
|
создаю поток mytrd
идея в том, что у всех потоков одинаковый код, но на стадии инициализации переменным присваиваются разные значения
например "com1","com2","com3" и т.д.
а целиком?
а что целиком?
|
|
|
|
|
|
bred
А моск есть?
Участник
Сказали спасибо: +6/-0
Offline
Сообщений: 387
Нет - это фантастика!
|
|
« Ответ #16 : 10 Апрель 2008, 11:21:10 »
|
|
в .h файле mytrd *mtr;
в .cpp
for (i = 0; i < 7; i++) mtr[i]= new (nothrow) mytrd(true); выдает ошибку: VCL style classes must be constructed using operator new
оператор new есть, что не так
что-то мне кажется что те надо добавить скобочки в объявление:
mytrd *mtr[N];
|
|
|
|
|
|
serg76
Участник
Сказали спасибо: +38/-2
Offline
Сообщений: 575
|
|
« Ответ #17 : 10 Апрель 2008, 12:11:26 »
|
|
2bred спасибо помогло
в динамическом выделении слабо орентируюсь
а как замутить если кол-во потоков заранее неизвесно ?
|
|
|
|
|
|
oxotnik
Глобальный модератор
Сказали спасибо: +100/-15
Offline
Сообщений: 2425
|
|
« Ответ #18 : 10 Апрель 2008, 14:01:04 »
|
|
а как замутить если кол-во потоков заранее неизвесно ?
я так делал, правда через CreateThread (собственно уже где то размещал):
//в *.hpp главной формы (у меня, а там делай где хочешь) #include using namespace std; class TMainForm : public TForm { ... public: deque <HANDLE> m_MyThread; .... }; //в *.cpp m_MyThread.push_back(CreateThread( NULL , 0 , SaveDocObj, (LPVOID)id, 0 , NULL )); // помещаем хендл потока в динамический массив //при закрытии формы (приложения) ждем завершения всех потоков: void __fastcall TMainForm::FormCloseQuery(TObject *Sender, bool &CanClose) { if (m_MyThread.size()>0) { HANDLE *MyThread = new HANDLE[m_MyThread.size()]; for(unsigned int n=0;n <m_MyThread.size();n++) { MyThread[n] = m_MyThread[n]; } DWORD hEvent = WaitForMultipleObjects(m_MyThread.size(), MyThread, TRUE, INFINITE); delete [] MyThread; if (hEvent != WAIT_OBJECT_0) { CanClose = false; return; } }
|
|
|
|
|
|
serg76
Участник
Сказали спасибо: +38/-2
Offline
Сообщений: 575
|
|
« Ответ #19 : 10 Апрель 2008, 16:43:03 »
|
|
2oxotnik спасибо, буду грызть
|
|
|
|
|
|