Multithreading 在Delphi XE2的无限等待线程中调用哪个等待方法
如果我有Multithreading 在Delphi XE2的无限等待线程中调用哪个等待方法,multithreading,delphi,delphi-xe2,Multithreading,Delphi,Delphi Xe2,如果我有 While not terminated do begin doStuff; end 在delphixe2线程的execute方法中循环,我不想让它成为我所有失败的一部分 我该叫什么 在Delphi7中,这很简单,我会调用Sleep(X),其中X与我认为线程的有趣程度成反比 但是现在,我有 SpinWait(X); 调用YieldX处理器的次数 及 它调用windows函数“SwitchToThread” 我应该使用其中任何一个还是只设置线程的优先级?SpinWait在
While not terminated do
begin
doStuff;
end
在delphixe2线程的execute方法中循环,我不想让它成为我所有失败的一部分
我该叫什么
在Delphi7中,这很简单,我会调用Sleep(X),其中X与我认为线程的有趣程度成反比
但是现在,我有
SpinWait(X);
调用YieldX处理器的次数
及
它调用windows函数“SwitchToThread”
我应该使用其中任何一个还是只设置线程的优先级?
SpinWait
在不放弃处理器的情况下浪费时间。这类似于睡眠
,但在延迟期间不会将控制权让给任何其他线程。如果你没有多个内核,那就完全是浪费,因为在你旋转的时候没有其他线程可以做任何事情。据我所知,Yield
类似于Sleep(0)
,只是如果没有其他线程准备运行,那么调用线程将立即继续
如果你知道你的线程真的没有别的事可做,那么这两个听起来都不像你想要的
最好的解决方案是找到或建立一些可等待的对象(如信号量、事件或进程句柄),您可以等待这些对象发出信号。这样,您就不必费心醒来,只需轮询您的状态并再次进入睡眠状态。线程池示例:
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.
unitthreadpool;
接口
使用
窗口、消息、系统工具、变体、类、图形、控件、窗体、,
对话框、StdCtrls、contnrs、syncobjs;
类型
TpooledTask=类(TObject)
私有的
Fonplete:TNotifyEvent;
受保护的
Fparam:TObject;
程序执行;事实上的摘要
公众的
构造函数创建(onComplete:TNotifyEvent;param:TObject);
结束;
TThreadPool=class(TObjectQueue)
私有的
访问:TcriticalSection;
任务计数器:THandle;
threadCount:整数;
公众的
构造函数创建(initThreads:integer);
程序添加任务(aTask:TpooledTask);
结束;
TpoolThread=class(Tthread)
私有的
FmyPool:TThreadPool;
受保护的
程序执行;推翻
公众的
构造函数创建(池:TThreadPool);
结束;
实施
{TpooledTask}
构造函数tpooleTask.create(onComplete:TNotifyEvent;param:TObject);
开始
Fonplete:=未完成;
Fparam:=参数;
结束;
{TThreadPool}
过程TThreadPool.addTask(aTask:TpooledTask);
开始
获取;
尝试
推送(aTask);
最后
获取、释放;
结束;
释放信号量(任务计数器,1,无);//释放一个单元到信号灯
结束;
构造函数TThreadPool.create(initThreads:integer);
开始
继承创造;
访问权限:=TcriticalSection.create;
taskCounter:=CreateSamphore(nil,0,maxInt,”);
虽然(ThreadCount等待事件有什么不对?在这种情况下,可以将线程置于睡眠状态,直到事件发出信号。你必须对同步对象进行适当的等待。睡眠
永远不是答案。永远都不会。@DavidHeffernan truer words很少说。谢谢你的提示。我正在做一些快速而肮脏的事情。进程正在运行这里不是一个长寿命的后台线程。我正在尝试修复这个更像“deadpool.pas”的“threadpool.pas”单元made buy是一个刚离开我们公司的家伙,他有一个收益率、windows事件句柄和tthreadedqueues的混合体。我会在事情运行后将合法的delphi事件放回。操作系统已经提供了一个线程池。广受赞誉的OmniThreadLibrary也提供了线程池。与其花时间研究如何修复损坏的东西,哟你可以把时间花在切换到已经知道可以工作的东西上。@Peter:如果你想替换一个坏的线程池,有没有办法把接口重新包装成包装器?@Mason我会尝试下一个版本。但这是“上周需要做的事情”之一至少该单元是通用的,足够短,可以完全废弃和替换。Delphi threadpool琐碎。TObjectQueue、Tsemaphore、TcriticalSection和一些TThreads。它大约有30-40行。天哪,看起来完全一样的代码,他一定是从web上下载的!好吧,可能不是,我要尝试一下看看会有什么结果。他中间有一些TThreadManager。这只是一些相同的东西。从D3开始使用基本相同的设计。好的,这个精简版本没有内置的ExceptionOn陷阱等,但我从来没有失败过。“TThreadManager”-微观管理线程是错误的….“非常困难”,并且容易出现“异常和意外的错误”来自所需功能的证据。哇,同样的结果,一定是他编程的另一部分内存泄漏!但当我试图杀死你的线程池时,它实际上死了,多谢了!
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.