3

如果我有一个

While not terminated do
begin
     doStuff;

end

在 Delphi XE2 线程的执行方法中循环,我不想让它成为我所有的失败者。

我该怎么称呼,

在 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 回答