我在线阅读Nick Hodges并且我发现了Queue,但它并没有像我预期的那样表现,我无法理解他和文档所说的内容。看看这段代码:
TThread.CreateAnonymousThread(
procedure
begin
TThread.Queue(TThread.Current, procedure
begin
Memo1.Lines.Clear;
Memo1.Lines.Add('start');
end);
Sleep(2000);
TThread.Synchronize(TThread.Current, procedure
begin
Memo1.Lines.Add('end');
end);
end
).Start;
我总是使用Synchronize
,但这次我尝试使用Queue
,因为根据Nick的说法,如果有多个请求,那就更好了,因为他们不会被"序列化&#34 ;并逐一执行。上面的代码工作正常。为什么这不起作用?
TThread.CreateAnonymousThread(
procedure
begin
TThread.Queue(TThread.Current, procedure
begin
Memo1.Lines.Clear;
Memo1.Lines.Add('start');
end);
Sleep(2000);
TThread.Queue(TThread.Current, procedure
begin
Memo1.Lines.Add('end');
end);
end
).Start;
在这种情况下,备忘录输出start
但不输出结尾。我打电话的时候:
start
答案 0 :(得分:18)
队列和同步之间的区别在于Synchronize()
将调用放入队列并等待该调用完成,Queue()
将调用放入队列并直接将控制返回给线程。
然而......在官方文档中未提及,当线程完成时,所有调用都放在队列中Queue(AThread, AMethod)
,其中AThread是自己的主题,已删除。
您可以在TThread.Destroy()
的来源中清楚地看到RemoveQueuedEvents(Self)
被调用。
RemoveQueuedEvents删除排队的方法调用。 [...]如果指定了AThread,则删除该线程排队的所有方法调用。
因此,在您的最后一个Queue()
线程结束后,TThread.Destroy()
将被执行,并且最后一次调用将从队列中删除。
你可以采取一些措施来解决这个问题。
TThread.Queue(nil, AMethod)
。 B.T.W.调用TThread.Queue(AMethod)
与TThread.Queue(Self, AMethod)
相同,因此如果线程即将结束并且您希望调用完成,则您始终需要使用nil-variant。Synchronize()
作为最后一个队列方法来实现。请注意,最后一次同步不必是真正的过程。您可以在TThread.Execute
Synchronize(DummySync)
(example)的末尾调用同步到虚拟过程。队列如果是FIFO,那么线程将等待,直到处理队列中的所有调用(包括空dummysync)。可在这些页面上找到一些额外信息
Ensure all TThread.Queue methods complete before thread self-destructs
http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/