Многопоточное приложение Delphi 7 - проблема с завершением приложения - PullRequest
1 голос
/ 17 декабря 2010

У меня есть потомок TThread и список объектов, каждый из которых имеет свою собственную копию такого потока и все же объект Event, созданный с помощью API CreateEvent ().

Различные объекты взаимодействуют друг с другом, вызывая событие.Т.е. каждый поток должен ждать, пока какой-то другой поток не запустит свое событие.Конечно, есть один «главный» поток, который работает постоянно, поэтому самоблокировка никогда не произойдет.Эта система прекрасно работает до конца метода Execute в каждом объекте.

Проблема возникает, когда я пытаюсь прервать все потоки, например, закрыв приложение.В этом случае мне нужна некоторая внешняя функция, которая вызывает метод Terminate каждого потока:

  for i := 0 to FLayers.Count - 1 do
  begin
    FLayers.Layer[i].FTerminating := true;
    f := true;
    while f do
    begin
      f := FLayers.Layer[i].IsActive;
      if f then
      begin
        Sleep(100);
        Application.ProcessMessages;
      end;
    end;
    FLayers.Layer[i].FTerminating := false;
  end;

Эта функция находится в событии Form.OnClose ().

Проблема в том, что около двух потоковзавершаются нормально, но другие все останавливаются при вызове WaitForSingleObject ():

procedure TLayerThread.Execute;
begin
FLayer.FIsActive := true;
...............
repeat
 //
 if Terminated or
   FLayer.FTerminating or
   (FLayer.FEvent = INVALID_HANDLE_VALUE) then
   begin
     break;
   end;
 //
 Fres := WaitForSingleObject(FLayer.FEvent, 100); <<<<<<<<<<<<<<<<<<<<<<<<
until Fres <> WAIT_TIMEOUT;
...........
FLayer.FIsActive := false;
end;

Все потоки просто остановлены (зависание) на линии.отмечен выше, несмотря на то, что значение времени ожидания установлено.

Есть идеи?

Использую Delphi 7 и Win XP.

Заранее спасибо.

Продолжение-

Я обнаружил, что проблема заключается в вызове Synchronize () из метода Execute ().Я не могу понять, что здесь не так.Synchronize () вызывает обычные вещи, такие как обновление визуальных элементов управления и ничего более.

Как показывает отладчик, мои потоки зависают при вызове WaitForSingleObject (), но это не то, что я использую в методе Execute ()координировать разные потоки, но какой-то другой вызов.Я могу предположить, что это здесь:

class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord);
.................
        LeaveCriticalSection(ThreadLock);
        try
          WaitForSingleObject(SyncProc.Signal, INFINITE);<<<<<<<<<<<<<<<<<<<<<<
        finally
          EnterCriticalSection(ThreadLock);
        end;
..................

Есть ли кто-нибудь там, кто мог бы сказать мне, что не так в моем коде?Я никогда не слышал, что нельзя вызывать Synchronize () из метода Execute () ...

1 Ответ

1 голос
/ 17 декабря 2010

Вместо WaitForSingleObject вы должны использовать WaitForMultipleObjects с бесконечным тайм-аутом и ожиданием двух событий, вашего FLayer.FEvent и второго события завершения.

AFAIR вы должны создать одно событие завершения для каждого процесса. Если WaitForMultipleObjects возвращает идентификатор события завершения, выйдите из цикла.

В методе OnClose () вы просто должны сигнализировать все события завершения.

...