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.