Self在Delphi中挂起一个不需要的线程并安全恢复

Ric*_*ler 6 delphi resume multithreading suspend

这个问题涉及Delphi和XE特别弃用Suspend和Resume.我已阅读其他帖子,到目前为止我还没有找到类似的用法,所以我将继续讨论并要求进行讨论.

我想知道有什么更好的方法可以在不需要时暂停线程?

我们有一个多年来使用的Delphi类,它基本上是一个与线程进程相关联的FIFO队列.队列接受主线程上的数据对象,如果线程被挂起,它将恢复它.

作为线程的Execute进程的一部分,对象从队列中弹出并在线程上处理.通常这是进行数据库查找.

在进程结束时,对象的属性将更新并标记为主线程可用或传递给另一个队列.执行过程的最后一步(实际上是第一步)是检查队列中是否还有其他项.如果有继续,否则它自行暂停.

它们是键,它在执行循环完成时是唯一的挂起操作,并且在将新项放入队列时调用正常操作期间的唯一恢复.例外是队列类被终止时.

恢复功能看起来像这样.

process TthrdQueue.MyResume();
  begin
    if Suspended then begin
      Sleep(1); //Allow thread to suspend if it is in the process of suspending
      Resume();
    end;
  end;
Run Code Online (Sandbox Code Playgroud)

执行看起来与此类似

process TthrdQueue.Execute();
  var
    Obj : TMyObject;
  begin
    inherited;
    FreeOnTerminate := true;
    while not terminated do begin
      if not Queue.Empty then begin
        Obj :=  Pop();
        MyProcess(Obj);  //Do work
        Obj.Ready := true;
      end
      else
        Suspend();  // No more Work
    end;   //Queue clean up in Destructor
  end;  
Run Code Online (Sandbox Code Playgroud)

TthrdQueue Push例程在堆栈中添加另一个对象后调用MyResume.如果线程被挂起,MyResume只调用Resume.

关闭时,我们将terminate设置为true,如果它被挂起则调用MyResume.

klu*_*udg 6

我建议使用以下TthrdQueue实现:

type
  TthrdQueue = class(TThread)
  private
    FEvent: THandle;
  protected
    procedure Execute; override;
  public
    procedure MyResume;
  end;

implementation

procedure TthrdQueue.MyResume;
begin
  SetEvent(FEvent);
end;

procedure TthrdQueue.Execute;
begin
  FEvent:= CreateEvent(nil,
                       False,    // auto reset
                       False,    // initial state = not signaled
                       nil);
  FreeOnTerminate := true;
  try
    while not Terminated do begin
      if not Queue.Empty then begin
        Obj :=  Pop();
        MyProcess(Obj);  //Do work
        Obj.Ready := true;
      end
      else
        WaitForSingleObject(FEvent, INFINITE);  // No more Work
    end;
  finally
    CloseHandle(FEvent);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

  • 他提到他在Delphi XE上,因此他已经可以访问Generics.Collections单元中的TThreadedQueue泛型类.TThreadedQueue是一个FIFO队列,能够在推送和弹出时同步线程. (2认同)