Kann die TPL die Aufgabe für mehr als einen Thread ausführen?

8

Mono / Xamarin-spezifische Antworten sind willkommen.

Ich verwende System.Threading.Tasks mit Task.Run (). Wird die TPL die erstellte Aufgabe für die Dauer der Ausführung der Aufgabe einem einzigen Thread zuweisen? Oder ist es möglich, dass die erstellte Aufgabe beim Ausführen vorzeitig beendet wird und dann erneut in einem anderen Thread geplant wird?

Wird Thread.CurrentThread.ManagedThreadId während der Lebensdauer einer Aufgabe konstant sein?

Ist die Antwort für lang andauernde Aufgaben anders?

Gibt es eine Möglichkeit, TPL-Verhalten in dieser Hinsicht zu kontrollieren?

    
jeff7091 25.07.2014, 15:45
quelle

2 Antworten

4
  

Wird die TPL die erstellte Aufgabe für die Dauer der Ausführung der Aufgabe einem einzigen Thread zuweisen?

Die Richtlinie besagt, dass synchrone Teile der Arbeit in einem einzelnen Thread ausgeführt werden. Wenn Sie also einen synchronen Delegaten an Task.Run übergeben, wird alles auf einem einzelnen Thread ausgeführt:

%Vor%

Wenn Sie jedoch über asynchronen Code verfügen, ist jedes await eine Stelle im Code, an der die Methode ausgesetzt ist. Wenn die Methode fortgesetzt wird, wird sie in einem Threadpool-Thread fortgesetzt (der ein anderer Thread sein kann).

%Vor%

Das lang laufende Flag (das nicht an Task.Run übergeben werden kann) hat keinen Einfluss auf dieses Verhalten, da es nur für den ersten synchronen Teil gilt.

Der normale Weg, dies zu kontrollieren, ist die Verwendung einer benutzerdefinierten TaskScheduler oder SynchronizationContext . Bevor Sie jedoch diesen Weg gehen, sollten Sie einen alternativen Ansatz in Betracht ziehen. Es sollte eine bessere Lösung geben, als die Methode auf denselben Thread zurückzusetzen. Zum Beispiel haben thread-affine Synchronisationsgrundelemente alle async -kompatible Entsprechungen, Thread-lokaler Speicher kann durch Closures / Klassenfelder / logischer Aufrufkontext usw. ersetzt werden.

    
Stephen Cleary 25.07.2014, 20:29
quelle
4

Task.Run plant, dass der Delegat im Thread-Pool ausgeführt wird, und der Thread-Pool führt den angegebenen Delegaten immer nur für einen einzelnen Thread aus. Es wird es nicht zwischen Threads bewegen.

Das heißt, ein Task ist konzeptionell nur die Darstellung der Beendigung einer asynchronen Operation zu irgendeinem Zeitpunkt in der Zukunft. Es kann alles darstellen, das letztendlich endet. Wenn Sie eine Aufgabe erstellen möchten, die die Ausführung eines Delegaten in einem Thread darstellt, dann die Ausführung eines anderen Delegaten in einem anderen Thread, dann können Sie das absolut tun.

Viele Methoden, die das Schlüsselwort async verwenden, tun dies tatsächlich. Da in einer Anwendung, für die kein Synchronisationskontext festgelegt ist, die Fortsetzungen, die als Ergebnis von await -Aufrufen verdrahtet sind, (sie können manchmal optimiert sein) im Thread-Pool separat geplant werden. Der folgende Code, der beispielsweise in einer Konsolenanwendung ausgeführt wird, generiert eine Aufgabe, die möglicherweise drei völlig unterschiedliche Zahlen ausgibt. (Natürlich sind sie nicht erforderlich , um anders zu sein; der Thread-Pool könnte einfach dazu führen, dass die Fortsetzungen so geplant werden, dass sie auf demselben Thread ausgeführt werden.)

%Vor%     
Servy 25.07.2014 15:49
quelle