Использование WaitForMultipleObjects в 64-битных приложениях Delphi: решение проблемы с ошибкой WAIT_FAILED
Вопрос, поднятый в данном запросе, касается использования функции WaitForMultipleObjects в контексте работы с 64 потоками в приложениях на Delphi. Разработчик столкнулся с проблемой, когда, несмотря на то что максимальное количество объектов для ожидания (MAXIMUM_WAIT_OBJECTS) согласно документации Microsoft составляет 64, функция возвращает ошибку WAIT_FAILED с кодом ошибки ERROR_INVALID_HANDLE. В данной статье мы рассмотрим причины возникновения этой проблемы и предложим пути её решения.
Проблема
Разработчик создаёт 64 потоков с помощью класса TWorkerThread и ожидает их завершения, используя функцию WaitForMultipleObjects. Однако, вместо успешного завершения, функция возвращает ошибку WAIT_FAILED, а GetLastError указывает на ERROR_INVALID_HANDLE.
Пример кода
procedure TForm1.Button1Click(Sender: TObject);
var
ArrayOfHandles: array of THandle;
Threads, x: byte;
ReturnValue: Cardinal;
begin
Threads := 64;
SetLength(ArrayOfHandles, Threads);
for x := 0 to Threads - 1 do
begin
WorkerThread := TWorkerThread.Create(True);
ArrayOfHandles[x] := WorkerThread.Handle;
WorkerThread.FreeOnTerminate := true;
WorkerThread.Priority := tpNormal;
WorkerThread.Resume;
end;
ReturnValue := WaitForMultipleObjects(Threads, @ArrayOfHandles[0], False, INFINITE);
ShowMessage('ReturnValue=' + IntToStr(ReturnValue) + #13 + 'GetLastError=' + IntToStr(GetLastError));
end;
Анализ проблемы
Проблема заключается в том, что разработчик предполагает, что все созданные потоки будут существовать в момент вызова WaitForMultipleObjects. Однако, если потоки завершаются до вызова этой функции, то дескрипторы процессов, переданные в функцию, становятся недействительными, что и вызывает ошибку ERROR_INVALID_HANDLE.
Подтвержденный ответ
Для решения проблемы необходимо убедиться, что все потоки ещё активны в момент вызова WaitForMultipleObjects. Если потоки должны завершаться, их дескрипторы не должны использоваться для ожидания. Альтернативный подход заключается в использовании механизмов синхронизации, таких как события или мютексы, которые будут оповещать основной поток о завершении работы потоков.
Альтернативный ответ и комментарии
Разработчик также предположил, что проблема может быть связана с установкой FreeOnTerminate в False, но это не является решением. Основная проблема в том, что после создания потоков и вызова Resume, они могут завершиться до вызова WaitForMultipleObjects. Следовательно, использование дескрипторов уже завершившихся потоков приводит к ошибке.
Пример улучшенного кода
procedure TForm1.Button1Click(Sender: TObject);
var
Threads: array of TThread;
x: byte;
begin
SetLength(Threads, 64);
for x := 0 to High(Threads) do
begin
Threads[x] := TThread.CreateAnonymousThread(
procedure
begin
Sleep(Random(1000));
end);
Threads[x].Start;
end;
// Ждём завершения всех потоков
for x := 0 to High(Threads) do
Threads[x].WaitFor;
end;
В данном примере используется массив TThread, который позволяет безопасно ожидать завершения потоков без необходимости использования дескрипторов процессов.
Заключение
При работе с большим количеством потоков важно правильно управлять их жизненным циклом. Необходимо убедиться, что потоки существуют и активны в момент вызова функций синхронизации. Использование подходящих механизмов синхронизации и правильное управление ресурсами поможет избежать возникновения подобных ошибок.
Разработчик использует функцию `WaitForMultipleObjects` в 64-битном приложении на Delphi для ожидания завершения множества потоков, но столкнулся с проблемой ошибки `WAIT_FAILED` из-за недействительных дескрипторов потоков.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.