简体   繁体   English

多线程Delphi 7应用程序-应用程序终止问题

[英]Multithreaded Delphi 7 App - a problem with app termination

I have a descendent of TThread and a list of objects, each with its own copy of such thread and yet the Event object, created with CreateEvent() API. 我有一个TThread的后代和一个对象列表,每个对象都有其自己的此类线程副本,但还有使用CreateEvent()API创建的Event对象。

Different objects interact with each other by event firing. 不同的对象通过事件触发彼此交互。 Ie each thread must wait until some other thread will fire its event. 也就是说,每个线程必须等待,直到其他某个线程触发其事件。 Of course, there is one "master" thread, which works permanently, so self-blocking could never happen. 当然,有一个“主”线程可以永久工作,因此永远不会发生自阻塞。 This system works just fine upto the end of the Execute method in each object. 该系统在每个对象中直到Execute方法的末尾都可以正常工作。

The probkem appears when I'm trying to interrupt all threads, eg by app closing. 当我尝试中断所有线程时(例如通过关闭应用程序),将出现问题。 In this case I need some external function which calls Terminate method of each thread: 在这种情况下,我需要一些外部函数来调用每个线程的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;

This function sits in Form.OnClose() event. 此函数位于Form.OnClose()事件中。

The problem is that about two of threads are terminated normally, but other all are stopped at the WaitForSingleObject() call: 问题是大约有两个线程正常终止,而其他所有线程都在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;

All the threads are just stopped (hang) at the line. 所有线程都只是在该行停止 (挂起)。 marked above, despite the timeout value is set. 尽管设置了超时值,但上面标记的内容。

Any ideas? 有任何想法吗?

Am using Delphi 7 and Win XP. 我正在使用Delphi 7和Win XP。

Thanks in advance. 提前致谢。

Followup-- 跟进 -

I've found that the problem is covered in the Synchronize() call from within the Execute() method. 我发现问题是在Execute()方法中的Synchronize()调用中解决的。 I can't understand what is wrong here. 我不明白这里出了什么问题。 Synchronize() calls usual things like visual controls update and nothing more. Synchronize()调用了诸如可视控件更新之类的常规功能,仅此而已。

As debugger shows, nost of my threads are hanging on some WaitForSingleObject() call, but this is not what I use in the Execute() method to coordinate different threads, but some another call. 如调试器所示,我的线程几乎没有挂在某些WaitForSingleObject()调用上,但这不是我在Execute()方法中用于协调不同线程的函数,而是另一个调用。 I can suppose that it is here: 我可以假设它在这里:

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

Is there anybody out there, who could tell me what is wrong in my code? 外面有人可以告诉我我的代码有什么问题吗? I never heard that it is not allowed to call Synchronize() from within Execute() method... 我从未听说过不允许从Execute()方法中调用Synchronize()...

Instead of WaitForSingleObject you should use WaitForMultipleObjects with infinite timeout and waiting two events, your FLayer.FEvent and a second termination-event. 而不是WaitForSingleObject ,应该使用具有无限超时并等待两个事件(FLayer.FEvent和第二个终止事件)的WaitForMultipleObjects

AFAIR you have to create one termination-event per process. 事后,您必须为每个进程创建一个终止事件。 If WaitForMultipleObjects returns the ID of the termination-event exit the loop. 如果WaitForMultipleObjects返回终止事件的ID,则退出循环。

In the OnClose() method you simple have to signal all termination-events. 在OnClose()方法中,您必须简单地发出所有终止事件的信号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM