multithreading - 仅处理最后一个TThread任务并丢弃先前的线程

标签 multithreading delphi delphi-7

我有一个数据库应用程序,它非常类似于Threaded Delphi ADO Query,异步地获取数据库记录集。

每次用户单击刷新都会创建一个新的TDBThread以获取记录集。

发生这种情况时,我想放弃所有以前的请求,只处理最后一个。

因此,我创建了一个名为FRequestID的类字段,该字段在每次发出请求时都会增加。我不尝试取消/中止先前的请求,并且不保留对创建的线程的引用。

procedure TForm1.RefreshClick(Sender: TObject);
var
  T: TDBThread;
begin
  Inc(FRequestID);

  T := TDBThread.Create(True); // Suspended
  T.FreeOnTerminate := True;
  T.RequestID := FRequestID;
  T.SQL := 'select * from mytable where ...';  
  T.OnTerminate := DBThreadTerminate;
  T.Resume;
end;

并在终止时检查线程RequestID是否是最后一个FRequestID,然后才处理请求。
procedure TForm1.DBThreadTerminate(Sender: TObject);
var
  T: TDBThread;
begin
  T := TDBThread(Sender);
  if FRequestID = T.RequestID then
  begin  
    Memo1.Lines.Add('*** Thread terminated ok ' + IntToStr(T.RequestID));
    MainDS.RecordSet := T.RecordSet;
  end
  else
    Memo1.Lines.Add('Thread discarded: ' + IntToStr(T.RequestID ));
end;

我的问题是这种方法正确(并且线程安全),并且是否有更好的方法仅处理最后一个请求?

注意:我正在使用Delphi 7。

最佳答案

您的代码是线程安全的,并且在定义的意义上是正确的(我不认为您对该请求ID溢出整数限制)。似乎您知道您将无法终止您没有引用的线程,并且您正在浪费资源。值得补充的是,您将无法取消正在运行的DBMS操作,因为链接的代码实现了同步提取,仅在工作线程中执行,而ADO无法取消这些操作。

不过,有更好的方法可以做到这一点。您可以例如仅创建一个线程(因为每个任务创建一个线程对于频繁执行的任务而言效率低下),具有命令(队列或列表)的集合,并让线程休眠以等待系统事件指示的工作。

或者,也可以代替每个命令一个这样的线程来收集命令(但是在这里,您应该考虑一下应用程序中使用的命令数量)。

而且,您可以实现异步ADO执行(可以将其取消,因此您将中断正在运行的操作并执行另一个操作)。

关于multithreading - 仅处理最后一个TThread任务并丢弃先前的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46130011/

相关文章:

c# - 显示超过 24 小时的时间跨度的标准方法是什么?

Delphi - 字节数组[0..693] - 转 B64 编码字符串

德尔福7 : Execute application with administrator privileges

德尔福7到德尔福XE5

java - 为什么 ThreadPoolExecutor$Worker 扩展 AbstractQueuedSynchronizer

java - 如果同步块(synchronized block)中的锁对象发生更改,会发生什么情况

objective-c - Objective-C 中的线程 : most efficient way for an update?

delphi - 为什么无法使用 WinExec 启动 Windows Update 控制面板?

delphi - 无法对封闭数据集执行此操作

C++/Thrift:TThreadedServer::stop() 是线程安全的吗?