单独线程中的无限循环

时间:2012-03-15 07:17:19

标签: multithreading delphi

我有一些需要定期执行的数据库优化例程。我目前正在使用TTimer,但主要的VCL冻结并且非常hacky ...我想知道什么是最好的方法是具有低CPU消耗并执行这些例程。我认为将例程放在具有低线程优先级的单独线程中是最好的方法。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

如果可能的话,最好只编写所有线程来完成在特定时间完成的最重要的事情。如果您不确切知道自己在做什么,那么弄乱线程优先级会导致serious performance problems。相反,只需像这样编写你的线程:

  1. 有什么重要事吗?如果是这样的话。

  2. 有什么不重要的事吗?如果是这样,请做一点。

  3. 转到第1步。

  4. 假设你使用线程优先级。想象一下:

    1. 低优先级任务A抓取数据库锁。

    2. 普通优先级任务B需要大量CPU时间,它会从低优先级任务中窃取CPU。

    3. 普通优先级任务C需要访问数据库。但它无法运行,因为低优先级任务保持对数据库的锁定,任务B使CPU通过任务A。

    4. 现在,任务C必须等到任务B完成才能访问数据库。但它应该是任务B的时间限制。

答案 1 :(得分:1)

这样做的一种方法是创建“db optimization thread”,例如:

type
  // a record defining database connection
  TConnectionSettings = record
    DatabaseName: string;
    Server: string;
    Port: Word;
    UserName: string;
    Password: string;
  end;

type
  TDBOptimizationThread = class(TThread)
  private
    FConnection: TDatabaseConnection; // your database connection... I don't know what libraries you are using
    FQuery: TQuery; // your specific db query
  protected
    procedure Execute; override;
  public
    constructor Create(AConnectionSettings: TConnectionSettings;
    destructor Destroy; override;
  end;

implementation

constructor TDBOptimizationThread.Create(AConnectionSettings: TConnectionSettings;
begin
  inherited Create(True); // create suspended
  //FreeOnTerminate := True; // if you want it to be freed when you terminate it
  // create FConnection and FQuery objects
  // setup FConnection parameters based on AConnectionSettings
end;

destructor TDBOptimizationThread.Destroy;
begin
  // destroy objects
  inherited Destroy;
end;

procedure TDBOptimizationThread.Execute;
begin
  while NOT Terminated do
    try
      // check if it's time to run query
      // you can use a private variable of TDateTime type that will hold
      // last timestamp of when the query ran, etc.
      if ItsTimeToRunQuery then begin
        // check if we still have db connectivity
        if NOT FConnection.Connected then
          // ouch, try to connect...
          FConnection.Connect;
        FQuery.SQL.Text := 'Your optimization query';
        FQuery.Execute; // or ExecSQL or whatever the method is based on your db library
      end;
    except
      on E: Exception do begin
        // log exception, something went wrong!!
      end;
    end;
end;

在此线程中创建和销毁数据库连接非常重要,否则您将遇到问题......

所以,让我们开始一个db优化线程

...
var
  LConnSettings: TConnectionSettings;
  // you may want a private TDBOptimizationThread variable rather than
  // a variable in a method, but I leave that to you
  LDBOptimizationThread: TDBOptimizationThread;
begin
  LConnSettings.Database := 'MyDatabase';
  LConnSettings.Port := 1234;
  LConnSettings.Server := 'localhost';
  // continue with connection settings...
  LDBOptimizationThread := TDBOptimizationThread.Create(LConnSettings);
  LDBOptimizationThread.Start; // start it
end;

你当然可以把它作为一个低优先级,但如果你的查询每次都不会运行超过几秒钟,我没有看到这个原因,但可以随意反驳。

答案 2 :(得分:0)

恕我直言,低优先级线程是实现此类任务的方法。但是您不必为每个优化例程创建不同的线程,只需要一个线程来处理所有这些线程。因此,您可以更容易地按特定顺序或以不同的频率执行它们,并且您将确保它们不会相互影响(从DB的角度来看)。