Delphi-Warteschlange und Synchronisieren

9

Ich lese Nick Hodges online und ich habe die Warteschlange entdeckt, aber es verhält sich nicht so, wie ich es erwartet habe und ich konnte nicht verstehen, was er und die Dokumentation sagen. Schau dir diesen Code an:

%Vor%

Ich benutze immer Synchronize , aber dieses Mal habe ich versucht mit Queue , denn laut Nick ist es besser im Falle von Mehrfachanfragen, da sie nicht "serialisiert" und nacheinander ausgeführt werden. Der obige Code funktioniert einwandfrei. Warum funktioniert das nicht stattdessen?

%Vor%

In diesem Fall gibt das Memo start aus, aber nicht das Ende. Wenn ich anrufe:

  • Synchronisiere auf dem ersten und Synchronisiere auf dem zweiten funktioniert es
  • Warteschlange auf der ersten und Synchronisieren auf der zweiten funktioniert
  • Warte beide Male, es funktioniert nicht, weil ich nur die start im Memo
  • sehe
Raffaele Rossi 16.02.2017, 17:31
quelle

1 Antwort

11

Der Unterschied zwischen Warteschlange und Synchronisierung besteht darin, dass Synchronize() den Wert " ruft eine Warteschlange auf und wartet darauf, dass dieser Anruf abgeschlossen wird, und Queue() Versetzt den Anruf in die Warteschlange und gibt die Steuerung direkt an den Thread zurück.

Allerdings ... und das wird nicht erwähnt in der offiziellen Dokumentation, wenn ein Thread fertig ist, alle Anrufe in der Warteschlange mit Queue(AThread, AMethod) , wobei AThread das eigene thread, werden entfernt.

Das sieht man deutlich in der Quelle von TThread.Destroy() wo RemoveQueuedEvents(Self) heißt.

  

RemoveQueuedEvents entfernt in der Warteschlange befindliche Methodenaufrufe. [...] Wenn AThread angegeben wird, werden alle von diesem Thread in die Warteschlange gestellten Methodenaufrufe entfernt.

Also direkt nach dem letzten Queue() endet Ihr Thread, TThread.Destroy() wird ausgeführt und der / die letzte (n) Anruf (e) wird / werden aus der Warteschlange entfernt.

Es gibt einige Dinge, die Sie tun können, um dies zu lösen.

  • Wie in den Kommentaren erwähnt, können Sie TThread.Queue(nil, AMethod) aufrufen. B.T.W. Der Aufruf von TThread.Queue(AMethod) ist identisch mit TThread.Queue(Self, AMethod) , so dass Sie immer die nil-Variante verwenden müssen, wenn der Thread endet und Sie möchten, dass der Aufruf beendet wird.
  • Aber ... Wenn Sie immer noch den Thread aktiv () benötigen, wenn Sie den Aufruf ausführen (für einige Daten davon), müssen Sie verhindern, dass der Thread beendet wird. Sie können dies tun, indem Sie Synchronize() als letzte Queue-Methode verwenden. Beachten Sie, dass die letzte Synchronisierung keine echte Prozedur sein muss. Sie können einfach am Ende des TThread.Execute like Synchronize(DummySync) ( Beispiels ) eine Dummy-Prozedur aufrufen. Die Warteschlange, wenn FIFO so der Thread wird warten, bis alle Anrufe in der Warteschlange verarbeitet werden (einschließlich der leeren Dummysync).

Einige zusätzliche Informationen finden Sie auf diesen Seiten. Stellen Sie sicher, dass alle TThread.Queue-Methoden abgeschlossen sind, bevor der Thread sich selbst zerstört
Ссылка

    
Rik 16.02.2017, 18:53
quelle

Tags und Links