Fehler in TPL - TaskContinuationOptions.ExecuteSynchronously?

8

Ich glaube, ich habe in TPL einen ernsthaften Fehler entdeckt. Ich bin nicht sicher. Ich habe viel Zeit damit verbracht, mich am Kopf zu kratzen und kann das Verhalten nicht verstehen. Kann jemand helfen?

Was mein Szenario ist:

  1. Ich erstelle eine Aufgabe, die einfache Dinge tut. Keine Ausnahmen usw.
  2. Ich registriere eine Fortsetzung mit ExecuteSynchronously set. Es muss auf demselben Thread sein.
  3. Ich starte die Aufgabe auf dem Standard Taskplaner (ThreadPool). Der Start-Thread wird fortgesetzt und wartet darauf.
  4. Die Aufgabe beginnt. Geht vorbei.
  5. Die Fortsetzung beginnt im selben Thread wie Aufgabe (vorherige Aufgabe abgeschlossen!) und tritt in Endlosschleife ein.
  6. Nichts passiert mit wartendem Thread. Will nicht weiter gehen. Festhalten warten. Ich habe Debugger eingecheckt, Aufgabe ist RunToCompletion.

Hier ist mein Code. Schätze jede Hilfe!

%Vor%     
Sławomir Nidecki 27.05.2012, 15:59
quelle

3 Antworten

5

Habe einen Fehler bei connect in deinem Namen abgelegt - hoffe das ist ok:)

Ссылка

Ich stimme zu, dass es sich um einen Fehler handelt, der nur ein Code-Snippet veröffentlichen möchte, das das Problem ohne "endlose" Wartezeit anzeigt. Der Fehler besteht darin, dass ExecuteSynchronously bedeutet, dass Wait-Aufrufe bei der ersten Task nicht zurückgegeben werden, bis die ExecuteSynchronous-Fortsetzungen ebenfalls abgeschlossen sind.

Wenn Sie das folgende Snippet ausführen, wird es 17 Sekunden lang angezeigt (also mussten alle 3 abgeschlossen werden, anstatt nur die erste). Es ist das gleiche, ob die dritte Aufgabe von der ersten oder der zweiten geplant wird (also wird sich ExecuteSynchronously durch die Baumstruktur von Aufgaben fortsetzen, die als solche geplant sind).

%Vor%

Das einzige, was mich daran erinnert, dass möglicherweise absichtlich ist (und daher eher ein doc-Fehler als ein Code-Fehler), ist Stephens Kommentar in diesem Blogpost :

  

ExecuteSynchronously ist eine Anforderung für eine Optimierung, die ausgeführt werden soll   Fortsetzungsaufgabe auf demselben Thread, der den Vorgänger vervollständigt hat   Aufgabe von denen wir fortfuhren, in der Tat läuft die Fortsetzung als   Teil des Übergangs des Antezedens zu einem Endzustand

    
James Manning 27.05.2012 17:23
quelle
3

Dieses Verhalten ist sinnvoll, wenn Sie Inlining von Aufgaben in Betracht ziehen. Wenn Sie Task.Wait aufrufen, bevor die Ausführung der Task begonnen hat, wird der Scheduler versuchen, sie zu inline zu schreiben, d. H. Sie in demselben Thread auszuführen, der Task.Wait aufgerufen hat. Das macht Sinn - warum einen Thread verschwenden, der auf die Aufgabe wartet, wenn Sie den Thread wiederverwenden können, um die Aufgabe auszuführen?

Wenn nun ExecuteSynchronously angegeben wird, wird der Scheduler angewiesen, die Fortsetzung im selben Thread wie die Antezedens-Task auszuführen - was beim Inlining der ursprüngliche aufrufende Thread ist.

Beachten Sie, dass wenn das Inlining nicht stattfindet, das von Ihnen erwartete Verhalten stattfindet . Alles, was Sie tun müssen, ist Inlining zu verbieten, und das ist einfach - entweder geben Sie ein Timeout für die Wartezeit an oder übergeben Sie ein Abbruch-Token, z. B.

%Vor%

Beachten Sie, dass Inlining nicht garantiert ist. Auf meinem Rechner ist das nicht passiert, weil die Aufgabe bereits vor dem Wait Aufruf begonnen hat, also mein Wait Aufruf nicht blockiert hat. Wenn Sie einen reproduzierbaren Block wünschen, rufen Sie Task.RunSynchronously auf.

    
Ohad Schneider 28.05.2012 13:48
quelle
0

Es stellt sich heraus, dass es tatsächlich ein Fehler ist. Ich denke jeder stimmt zu. Wenn dies jedoch so aussehen sollte, scheinen die API und die Dokumente sehr irreführend zu sein.

Bei meiner Arbeit verwende ich einfach ManualResetEventSlim.

%Vor%

Vielen Dank, dass Sie sich das angesehen haben! Und für alle Kommentare.

Grüße.

    
Sławomir Nidecki 27.05.2012 18:45
quelle