![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
WaitForMultipleObjects [D7, WinXP]
Stas_Kalishenko © (2006-02-15 18:27:00)Помогите! WaitForMultipleObjects возвращает -1 (минус единицу). Что это означает?
Вот как вызываю:
ncount := WaitForMultipleObjects(t_count,@lpHandles,False,INFINITE);
где t_count=10,
ncount - тип integer
Stas_Kalishenko (2006-02-16 10:14:00) [1]Ок. Спасибо.
Digitman (2006-02-16 09:59:00) [2]WaitForMultipleObjects-функция у тебя как раз и занята ничем иным кроме как ожиданием тех самых сигналов, так что ничего нового изобретать не нужно.
var
lpHandles: array [0..t_count - 1] of Cardinal;
Threads: array [0..t_count - 1] of TThread;
ncount := WaitForMultipleObjects(t_count,@lpHandles,False,INFINITE);
Win32Check(ncount <> WAIT_FAILED);
//сначала разрушаем объект
Threads[ncount].Free;
//тут же воссоздаем его
Threads[ncount] := TSaldoThread.Create(True, //CREATE_SUSPENDED
Form1.DateTimePicker1.DateTime,
Form1.DateTimePicker2.DateTime,
ADOQuery.FieldByName('date_open').AsDateTime,
ADOQuery.FieldByName('acc').AsString,
ADOQuery.FieldByName('notice').AsString)
with Threads[ncount] do begin
lpHandles[ncount] := Handle; //зафиксировали хэндл
Resume; //разбудили поток
end;
begin...end (2006-02-16 09:56:00) [3]> Stas_Kalishenko (16.02.06 09:36) [12]
О завершении функции потока Вам просигналит WaitForMultipleObjects. После этого можно будет самостоятельно разрушить объект и закрыть хэндл, вызвав Free нужного экземпляра. Только указатели на экземпляры нужно сохранять.
Stas_Kalishenko (2006-02-16 09:52:00) [4]>>Установка FreeOnTerminate в True означает, что сразу после выхода из поточной функции будет вызван Destroy, т.е. объект потока будет уничтожен, и (что главное) -- будет закрыт дескриптор потока. После этого обращение к этому дескриптору будет давать ошибку.
Это я уже понял. Только как из созданного потока сигнализировать о своем завершении и обрабатывать это, пока не понял.
begin...end (2006-02-16 09:47:00) [5]> Stas_Kalishenko (16.02.06 09:14) [8]
Установка FreeOnTerminate в True означает, что сразу после выхода из поточной функции будет вызван Destroy, т.е. объект потока будет уничтожен, и (что главное) -- будет закрыт дескриптор потока. После этого обращение к этому дескриптору будет давать ошибку.
Stas_Kalishenko (2006-02-16 09:36:00) [6]А как именно сигналить о завершении? Можно пример?
Digitman (2006-02-16 09:30:00) [7]
> Thr.FreeOnTerminate := True
Убери автоуничтожение.
Когда тред просигналит о своем завершении, уничтожай его явно.
Stas_Kalishenko (2006-02-16 09:27:00) [8]Обнаружил такую дурацкую закономерность: если ставлю ограничение кол-ва потоков 10, то все выполняется до 90% от общего кол-ва потоков, т.е. если кол-во потоков 150, то выполняется из них примерно 135, а потом access violation (все это, конечно, без обработки ncount=-1, т.е. убрав if ncount = -1 then RaiseLastOSError). Если ставлю ограничение 5 потоков - вылетает примерно на 95%. А вот если ставлю ограничение на 2 потока, то все проходит гладко.
Stas_Kalishenko (2006-02-16 09:22:00) [9]Поправка к предыдущему посту: " создаю 10 потокови жду, когда хотя бы один из них завершится...".
>>Вероятно, в содержимом массива дескрипторов, адрес которого передаётся в WaitForMultipleObjects.
Неужели не те хендлы сохраняю? Впечатление такое, что пока WaitForMultipleObjects отрабатывает, т.е. возвращает значение хендла одного отработанного потока, завершает работу еще один поток (а может и несколько) и уничтожается. Поэтому при следующей отработке WaitForMultipleObjects возвращает ошибку. Если это так, то почему? Как уничтожать левые хендлы?
Stas_Kalishenko (2006-02-16 09:14:00) [10]Дело в том, что создаю потоки и жду, когда хотя бы один из них завершится, далее создаю следующий и жду снова, когда один из созданных завершится. Все идет вроде нормально до какого-то момента, а потом - access violation. Начал проверять отработку WaitForMultipleObjects, смотрю возвращает -1. Вот сам код цикла вызова потоков.
var Thr: TSaldoThread;
lpHandles: array [0..t_count - 1] of Cardinal;
ADOQuery: TADOQuery;
i, ncount: integer;
...
for i := 0 to ADOQuery.RecordCount - 1 do
begin
if i < t_count then
begin
Thr := TSaldoThread.Create(False,
Form1.DateTimePicker1.DateTime,
Form1.DateTimePicker2.DateTime,
ADOQuery.FieldByName('date_open').AsDateTime,
ADOQuery.FieldByName('acc').AsString,
ADOQuery.FieldByName('notice').AsString);
lpHandles[i] := Thr.Handle;
Thr.FreeOnTerminate := True;
end
else
begin
ncount := WaitForMultipleObjects(t_count,@lpHandles,False,INFINITE);
if ncount = -1 then
RaiseLastOSError
else
begin
Thr := TSaldoThread.Create(False,
Form1.DateTimePicker1.DateTime,
Form1.DateTimePicker2.DateTime,
ADOQuery.FieldByName('date_open').AsDateTime,
ADOQuery.FieldByName('acc').AsString,
ADOQuery.FieldByName('notice').AsString);
lpHandles[ncount] := Thr.Handle;
Thr.FreeOnTerminate := True; end;
end;
ADOQuery.Next;
end;
>>почему это он равен 10-ти?)
t_count у меня константа, равная 10 - ограничение количества запускаемых потоков. Но это не столь важно, она может быть какой угодно (в разумных пределах).
Marser (2006-02-16 02:07:00) [11]> [6] GuAV © (16.02.06 02:03)
>
> >?
> > Это не WAIT_FAILED.
>
> Это WAIT_FAILED.
>
> Просто оно интепреретировано как знаковое, т.к.
>
> > ncount := WaitForMultipleObjects
>
>
> > ncount - тип integer
Действительно... Беру свой вопрос назад.
GuAV (2006-02-16 02:03:00) [12]
>?
> Это не WAIT_FAILED.
Это WAIT_FAILED.
Просто оно интепреретировано как знаковое, т.к.
> ncount := WaitForMultipleObjects
> ncount - тип integer
Marser (2006-02-15 22:42:00) [13]> [1] begin...end © (15.02.06 18:35)
> Это означает WAIT_FAILED (ошибка).
WAIT_FAILED = DWORD($FFFFFFFF);
?
Это не WAIT_FAILED.
begin...end (2006-02-15 19:34:00) [14]> Stas_Kalishenko (15.02.06 18:47) [2]
> Где копать причину сбоя?
Вероятно, в содержимом массива дескрипторов, адрес которого передаётся в WaitForMultipleObjects. Код его заполнения можно увидеть?
kaZaNoVa (2006-02-15 18:56:00) [15]Stas_Kalishenko (15.02.06 18:47) [2]
> где t_count=10,
почему это он равен 10-ти?)
Stas_Kalishenko (2006-02-15 18:47:00) [16]Код ошибки - 6: Неверный дескриптор. Где копать причину сбоя?
begin...end (2006-02-15 18:35:00) [17]Это означает WAIT_FAILED (ошибка). Чтобы выяснить, какая именно, вызовите GetLastError.