3

私が持っている場合

While not terminated do
begin
     doStuff;

end

Delphi XE2 スレッドの execute メソッドでループし、すべてのフロップを台無しにしたくありません。

何と呼べばいいのか、

Delphi 7 では、それは簡単でした。Sleep(X) と呼びます。ここで、X はスレッドの面白さに反比例します。

しかし今、私は持っています

SpinWait(X);

YieldProcessor を X 回呼び出す

Yield;

Windows関数「SwitchToThread」を呼び出します。

これらのいずれかを使用する必要がありますか、それともスレッドの優先順位を設定する必要がありますか?

4

2 に答える 2

7

SpinWaitプロセッサをあきらめることなく時間を無駄にします。これはと似Sleepていますが、遅延中に他のスレッドに制御を譲ることはありません。複数のコアがない場合は、回転している間は他のスレッドが何もできないため、無駄になります。私が知る限り、実行する準備ができている他のスレッドがない場合、呼び出し元のスレッドはすぐに続行することを除いて、にYield類似しています。Sleep(0)

あなたのスレッドが本当に他に何もすることがないことを知っているなら、それらのどちらもあなたが望むもののようには聞こえません。

最善の解決策は、シグナルが送信されるのを待つことができる待機可能なオブジェクト(セマフォ、イベント、プロセスハンドルなど)を見つけるか確立することです。そうすれば、わざわざ目を覚ます必要がなくなり、ステータスをポーリングして再びスリープ状態にできるようになります。

于 2012-10-05T17:43:33.367 に答える
1

スレッドプールの例:

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.
于 2012-10-05T18:43:28.177 に答える