在Delphi XE2的无限等待线程中调用哪种wait方法

时间:2012-10-05 17:15:07

标签: multithreading delphi delphi-xe2

如果我有一个

While not terminated do
begin
     doStuff;

end

在Delphi XE2线程的execute方法中循环,我想不要让它变成bogart所有的翻牌。

我该怎么称呼,

在Delphi 7中,很简单,我称之为Sleep(X),其中X与我认为线程的有趣程度成反比。

但是现在,我已经

SpinWait(X);

其中调用YieldProcessor X次数

Yield;

调用windows函数“SwitchToThread”。

我应该使用其中任何一种,还是应该设置线程的优先级?

2 个答案:

答案 0 :(得分:7)

SpinWait浪费时间而不放弃处理器。它就像Sleep,但在延迟期间没有对任何其他线程进行控制。如果你没有多个核心,那么这是完全浪费,因为在你旋转时没有其他线程可以做任何事情。据我所知,Yield类似于Sleep(0),除非没有其他线程准备好运行,那么调用线程会立即继续。

如果你知道你的线程真的没有别的事可做,那么这些听起来都不是你想要的。

最好的解决方案是找到或建立一些您可以等待发出信号的可等待对象(如信号量,事件或进程句柄)。然后你根本不必费心醒来,这样你就可以轮询你的状态并再次入睡。

答案 1 :(得分:1)

Threadpool示例:

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.