如果我有一个
While not terminated do
begin
doStuff;
end
在Delphi XE2线程的execute方法中循环,我想不要让它变成bogart所有的翻牌。
我该怎么称呼,
在Delphi 7中,很简单,我称之为Sleep(X),其中X与我认为线程的有趣程度成反比。但是现在,我已经
了SpinWait(X);
其中调用YieldProcessor X次数
和
Yield;
调用windows函数“SwitchToThread”。
我应该使用其中任何一种,还是应该设置线程的优先级?
答案 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.