Multithreading 在Delphi中自挂起线程时';不需要,安全恢复
这个问题涉及到Delphi和XE,它们特别反对Suspend和Resume。我读过其他帖子,到目前为止还没有发现类似的用法,所以我将继续讨论 我想知道的是,有没有更好的方法在不需要线程时暂停它 我们有一个已经使用多年的Delphi类,它基本上是一个FIFO队列,与线程化进程关联。队列在主线程上接受一个数据对象,如果线程被挂起,它将恢复它 作为线程执行过程的一部分,对象将弹出队列并在线程上处理。通常这是为了进行数据库查找 在进程结束时,对象的属性将被更新并标记为可供主线程使用或传递给另一个队列。执行过程的最后一步(实际上是第一步)是检查队列中是否还有其他项。如果有,它将继续,否则它将暂停自己 当执行循环完成时,它们是唯一的挂起操作,而在正常操作期间,当队列中放置新项时,将调用唯一的恢复。队列类终止时会出现异常 resume函数看起来像这样Multithreading 在Delphi中自挂起线程时';不需要,安全恢复,multithreading,delphi,resume,suspend,Multithreading,Delphi,Resume,Suspend,这个问题涉及到Delphi和XE,它们特别反对Suspend和Resume。我读过其他帖子,到目前为止还没有发现类似的用法,所以我将继续讨论 我想知道的是,有没有更好的方法在不需要线程时暂停它 我们有一个已经使用多年的Delphi类,它基本上是一个FIFO队列,与线程化进程关联。队列在主线程上接受一个数据对象,如果线程被挂起,它将恢复它 作为线程执行过程的一部分,对象将弹出队列并在线程上处理。通常这是为了进行数据库查找 在进程结束时,对象的属性将被更新并标记为可供主线程使用或传递给另一个队列。执
process TthrdQueue.MyResume();
begin
if Suspended then begin
Sleep(1); //Allow thread to suspend if it is in the process of suspending
Resume();
end;
end;
execute看起来与此类似
process TthrdQueue.Execute();
var
Obj : TMyObject;
begin
inherited;
FreeOnTerminate := true;
while not terminated do begin
if not Queue.Empty then begin
Obj := Pop();
MyProcess(Obj); //Do work
Obj.Ready := true;
end
else
Suspend(); // No more Work
end; //Queue clean up in Destructor
end;
TthrdQueue Push例程在堆栈中添加另一个对象后调用MyResume。MyResume仅在线程挂起时调用Resume
关闭时,我们将terminate设置为true,如果MyResume被挂起,则调用它。我建议使用以下TthrdQueue实现:
type
TthrdQueue = class(TThread)
private
FEvent: THandle;
protected
procedure Execute; override;
public
procedure MyResume;
end;
implementation
procedure TthrdQueue.MyResume;
begin
SetEvent(FEvent);
end;
procedure TthrdQueue.Execute;
begin
FEvent:= CreateEvent(nil,
False, // auto reset
False, // initial state = not signaled
nil);
FreeOnTerminate := true;
try
while not Terminated do begin
if not Queue.Empty then begin
Obj := Pop();
MyProcess(Obj); //Do work
Obj.Ready := true;
end
else
WaitForSingleObject(FEvent, INFINITE); // No more Work
end;
finally
CloseHandle(FEvent);
end;
end;
不要暂停线程,而是让它休眠。使它阻塞在某个可等待句柄上,当该句柄发出信号时,线程将被唤醒 可等待对象有许多选项,包括事件、互斥对象、信号量、消息队列和管道 假设您选择使用一个事件。使其成为自动重置事件。当队列为空时,调用事件的
WaitFor
方法。当其他东西填充队列或想要退出时,让它调用事件的方法
我更喜欢的技术是使用OS消息队列。我将用消息替换您的队列对象。然后,编写一个标准的
GetMessage
循环。当队列为空时,它将自动阻塞以等待新消息。将终止请求转换为另一条消息。(一旦您开始对线程执行任何有趣的操作,那么TThread.Terminate
方法就不是一个非常有用的函数,因为它不是虚拟的。)有一个库允许在中实现生产者-消费者队列。这个场景实际上就是所讨论的示例
条件的经典例子
变量是生产者/消费者
问题一个或多个线程称为
生产者生产并添加项目
排队。使用者(其他线程)
通过删除已生成的
队列中的项目
我不是专家,但我会简单地使用Sleep(250)或SignalObjectAndWait(参见msdn)进行更精确的控制。他提到他在Delphi XE上,所以他已经可以访问Generics.Collections单元中的TThreadedQueue泛型类。TThreadedQueue是一个FIFO队列,具有在推送和弹出时同步线程的能力。我们的库中仍然支持很多Delphi7代码。但我将在未来的研究中关注TThreadedQueue。我喜欢给定的解决方案,因为它可以轻松地更新我们现有的代码。这看起来是一个很好的解决方案,但是你打算什么时候调用MyResume?队列会这样做吗?什么时候?它如何知道要唤醒哪些线程?或者,当一个项目添加到队列的后面时,您是否会立即唤醒所有正在睡眠的线程。我明白您使用Windows支持队列的意思。我们一直在使用的是很多现有的代码,现在已经足够好了。但我会在以后的工作中仔细研究它,我很喜欢它的自动性。非常感谢。