Текущий архив: 2006.05.07;
Скачать: CL | DM;
ВнизWaitForMultipleObjects Найти похожие ветки
← →
Stas_Kalishenko (2006-02-15 18:27) [0]Помогите! WaitForMultipleObjects возвращает -1 (минус единицу). Что это означает?
Вот как вызываю:
ncount := WaitForMultipleObjects(t_count,@lpHandles,False,INFINITE);
где t_count=10,
ncount - тип integer
← →
begin...end © (2006-02-15 18:35) [1]Это означает WAIT_FAILED (ошибка). Чтобы выяснить, какая именно, вызовите GetLastError.
← →
Stas_Kalishenko (2006-02-15 18:47) [2]Код ошибки - 6: Неверный дескриптор. Где копать причину сбоя?
← →
kaZaNoVa © (2006-02-15 18:56) [3]Stas_Kalishenko (15.02.06 18:47) [2]
> где t_count=10,
почему это он равен 10-ти?)
← →
begin...end © (2006-02-15 19:34) [4]> Stas_Kalishenko (15.02.06 18:47) [2]
> Где копать причину сбоя?
Вероятно, в содержимом массива дескрипторов, адрес которого передаётся в WaitForMultipleObjects. Код его заполнения можно увидеть?
← →
Marser © (2006-02-15 22:42) [5]> [1] begin...end © (15.02.06 18:35)
> Это означает WAIT_FAILED (ошибка).
WAIT_FAILED = DWORD($FFFFFFFF);
?
Это не WAIT_FAILED.
← →
GuAV © (2006-02-16 02:03) [6]
>?
> Это не WAIT_FAILED.
Это WAIT_FAILED.
Просто оно интепреретировано как знаковое, т.к.
> ncount := WaitForMultipleObjects
> ncount - тип integer
← →
Marser © (2006-02-16 02:07) [7]> [6] GuAV © (16.02.06 02:03)
>
> >?
> > Это не WAIT_FAILED.
>
> Это WAIT_FAILED.
>
> Просто оно интепреретировано как знаковое, т.к.
>
> > ncount := WaitForMultipleObjects
>
>
> > ncount - тип integer
Действительно... Беру свой вопрос назад.
← →
Stas_Kalishenko (2006-02-16 09:14) [8]Дело в том, что создаю потоки и жду, когда хотя бы один из них завершится, далее создаю следующий и жду снова, когда один из созданных завершится. Все идет вроде нормально до какого-то момента, а потом - 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 - ограничение количества запускаемых потоков. Но это не столь важно, она может быть какой угодно (в разумных пределах).
← →
Stas_Kalishenko (2006-02-16 09:22) [9]Поправка к предыдущему посту: "создаю 10 потоков и жду, когда хотя бы один из них завершится...".
>>Вероятно, в содержимом массива дескрипторов, адрес которого передаётся в WaitForMultipleObjects.
Неужели не те хендлы сохраняю? Впечатление такое, что пока WaitForMultipleObjects отрабатывает, т.е. возвращает значение хендла одного отработанного потока, завершает работу еще один поток (а может и несколько) и уничтожается. Поэтому при следующей отработке WaitForMultipleObjects возвращает ошибку. Если это так, то почему? Как уничтожать левые хендлы?
← →
Stas_Kalishenko (2006-02-16 09:27) [10]Обнаружил такую дурацкую закономерность: если ставлю ограничение кол-ва потоков 10, то все выполняется до 90% от общего кол-ва потоков, т.е. если кол-во потоков 150, то выполняется из них примерно 135, а потом access violation (все это, конечно, без обработки ncount=-1, т.е. убрав if ncount = -1 then RaiseLastOSError). Если ставлю ограничение 5 потоков - вылетает примерно на 95%. А вот если ставлю ограничение на 2 потока, то все проходит гладко.
← →
Digitman © (2006-02-16 09:30) [11]
> Thr.FreeOnTerminate := True
Убери автоуничтожение.
Когда тред просигналит о своем завершении, уничтожай его явно.
← →
Stas_Kalishenko (2006-02-16 09:36) [12]А как именно сигналить о завершении? Можно пример?
← →
begin...end © (2006-02-16 09:47) [13]> Stas_Kalishenko (16.02.06 09:14) [8]
Установка FreeOnTerminate в True означает, что сразу после выхода из поточной функции будет вызван Destroy, т.е. объект потока будет уничтожен, и (что главное) -- будет закрыт дескриптор потока. После этого обращение к этому дескриптору будет давать ошибку.
← →
Stas_Kalishenko (2006-02-16 09:52) [14]>>Установка FreeOnTerminate в True означает, что сразу после выхода из поточной функции будет вызван Destroy, т.е. объект потока будет уничтожен, и (что главное) -- будет закрыт дескриптор потока. После этого обращение к этому дескриптору будет давать ошибку.
Это я уже понял. Только как из созданного потока сигнализировать о своем завершении и обрабатывать это, пока не понял.
← →
begin...end © (2006-02-16 09:56) [15]> Stas_Kalishenko (16.02.06 09:36) [12]
О завершении функции потока Вам просигналит WaitForMultipleObjects. После этого можно будет самостоятельно разрушить объект и закрыть хэндл, вызвав Free нужного экземпляра. Только указатели на экземпляры нужно сохранять.
← →
Digitman © (2006-02-16 09:59) [16]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;
← →
Stas_Kalishenko (2006-02-16 10:14) [17]Ок. Спасибо.
Страницы: 1 вся ветка
Текущий архив: 2006.05.07;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.011 c