Which wait method to call in an infinite waiting thread for Delphi XE2

大憨熊 提交于 2019-12-21 20:45:40

问题


if I've got a

While not terminated do
begin
     doStuff;

end

loop in the execute method of a Delphi XE2 thread, and I want to not make it bogart all my flops.

What should I call,

in Delphi 7, it was easy, I'd call Sleep(X) where X was inversely proportional to how interesting I thought the thread was.

But now, I've got

SpinWait(X);

Which calls YieldProcessor X number of times

and

Yield;

which calls the windows function "SwitchToThread".

Should I use any of these or should I just set the priority of the thread?


回答1:


SpinWait wastes time without giving up the processor. It's like Sleep, but without yielding control to any other threads during the delay. If you don't have multiple cores, then it's a total waste because no other thread can do anything while you're spinning. As far as I can tell, Yield is analogous to Sleep(0), except that if there is no other thread ready to run, then the calling thread just continues immediately.

Neither of those sounds like what you want if you know that your thread really has nothing else to do.

The best solution would be to find or establish some waitable object (like a semaphore, event, or process handle) that you could wait to become signaled. Then you wouldn't have to bother waking up at all, just so you can poll your status and go to sleep again.




回答2:


Threadpool example:

unit ThreadPool;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, contnrs, syncobjs;


    type

    TpooledTask=class(TObject)
    private
      FonComplete:TNotifyEvent;
    protected
      Fparam:TObject;
      procedure execute; virtual; abstract;
    public
      constructor create(onComplete:TNotifyEvent;param:TObject);
    end;

    TThreadPool=class(TObjectQueue)
    private
      access:TcriticalSection;
      taskCounter:THandle;
      threadCount:integer;
    public
      constructor create(initThreads:integer);
      procedure addTask(aTask:TpooledTask);
    end;

    TpoolThread=class(Tthread)
    private
      FmyPool:TThreadPool;
    protected
      procedure Execute; override;
    public
      constructor create(pool:TThreadPool);
    end;

    implementation

    { TpooledTask }

    constructor TpooledTask.create(onComplete: TNotifyEvent; param: TObject);
    begin
      FonComplete:=onComplete;
      Fparam:=param;
    end;

    { TThreadPool }

    procedure TThreadPool.addTask(aTask: TpooledTask);
    begin
      access.acquire;
      try
        push(aTask);
      finally
        access.release;
      end;
      releaseSemaphore(taskCounter,1,nil); // release one unit to semaphore
    end;

    constructor TThreadPool.create(initThreads: integer);
    begin
      inherited create;
      access:=TcriticalSection.create;
      taskCounter:=createSemaphore(nil,0,maxInt,'');
      while(threadCount<initThreads) do
      begin
        TpoolThread.create(self);
        inc(threadCount);
      end;
    end;

    { TpoolThread }

    constructor TpoolThread.create(pool: TThreadPool);
    begin
      inherited create(true);
      FmyPool:=pool;
      FreeOnTerminate:=true;
      resume;
    end;

    procedure TpoolThread.execute;
    var thisTask:TpooledTask;
    begin
      while (WAIT_OBJECT_0=waitForSingleObject(FmyPool.taskCounter,INFINITE)) do
      begin
        FmyPool.access.acquire;
        try
          thisTask:=TpooledTask(FmyPool.pop);
        finally
          FmyPool.access.release;
        end;
        thisTask.execute;
        if assigned(thisTask.FonComplete) then thisTask.FonComplete(thisTask);
      end;
    end;

    end.


来源:https://stackoverflow.com/questions/12751031/which-wait-method-to-call-in-an-infinite-waiting-thread-for-delphi-xe2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!