Welche der oben genannten Methoden werden parallel im async/away generiert, wenn ButtonClick aufgerufen wird?
Nur die innerhalb der Task.Run
.
Ich meine, was sollte meine Bedenken über Race Conditions mit async arbeiten/erwarten?
Ich schlage vor, Sie beginnen mit meinem async
intro lesen, die erklärt, wie await
tatsächlich funktioniert.
Zusammenfassend, async
Methoden werden in der Regel in einer seriell asynchronen Mode geschrieben. Nehmen Sie diesen Code zum Beispiel:
CodeBeforeAwait();
await SomeOtherMethodAsync();
CodeAfterAwait();
Sie immer sagen können, dass CodeBeforeAwait
ersten bis zum Abschluss ausgeführt wird, dann SomeOtherMethodAsync
aufgerufen.Dann wartet unsere Methode (asynchron) auf SomeOtherMethodAsync
, um abzuschließen, und erst danach wird CodeAfterAwait
aufgerufen.
So ist es seriell asynchron. Es wird seriell ausgeführt, so wie Sie es erwarten, aber auch mit einem asynchronen Punkt in diesem Fluss (await
).
Nun, sie kann nicht sagen, dassCodeBeforeAwait
und CodeAfterAwait
im selben Thread ausgeführt werden, zumindest nicht ohne mehr Kontext. await
wird standardmäßig im aktuellen SynchronizationContext
(oder dem aktuellen TaskScheduler
, wenn es kein SyncCtx gibt) fortgesetzt. Wenn also die obige Beispielmethode im UI-Thread ausgeführt wurde, wissen Sie, dass CodeBeforeAwait
und CodeAfterAwait
beide im UI-Thread ausgeführt werden. Wenn es jedoch ohne einen Kontext ausgeführt wurde (d. H. Von einem Hintergrundthread oder einem Console-Hauptthread), kann CodeAfterAwait
in einem anderen Thread ausgeführt werden.
Beachten Sie, dass selbst wenn Teile einer Methode in einem anderen Thread ausgeführt werden, die Runtime dafür sorgt, dass Barrieren gesetzt werden, bevor die Methode fortgesetzt wird.
Beachten Sie auch, dass Ihr ursprüngliches Beispiel Task.Run
verwendet, die explizit Arbeit auf dem Thread-Pool platziert. Das ist ganz anders als async
/await
, und Sie werden das Multithread definitiv behandeln müssen.
Sollte ich Mutex auf möglichen gemeinsamen Zustand verwenden?
Ja. Wenn Ihr Code beispielsweise Task.Run
verwendet, müssen Sie dies als separaten Thread behandeln. (Beachten Sie, dass es mit await
Los einfacher ist, den Status überhaupt nicht mit anderen Threads zu teilen - wenn Sie Ihre Hintergrundaufgaben sauber halten können, sind sie viel einfacher zu arbeiten).
Wenn ja, wie kann ich feststellen, was die gemeinsam genutzten Statusobjekte sind?
Gleiche Antwort wie bei jeder anderen Art von Multi-Thread-Code: Code-Inspektion.
Standardmäßig werden alle asynchronen Fortsetzungen im selben Synchronisierungskontext ausgeführt, den sie gestartet haben. In der Konsolenanwendung gibt es keinen Synchronisierungskontext und alle Aufgaben werden in einem Thread-Pool ausgeführt. Also ja, Sie sollten sich der Rennbedingungen bewusst sein. Gemeinsame Statusobjekte sind die Objekte, auf die in allen Aufgaben zugegriffen wird. – VMAtm
Hallo @VMAtm! Also wird das Aufrufdiagramm im selben Synchronisationskontext ausgeführt (ich denke, dies ist der gleiche wie ein Thread), bis es das erste "Warte" -Schlüsselwort findet? An diesem Punkt (Ausführung des ersten "Wartens" im Aufrufdiagramm) wird der Code unter "Warten" in einem anderen Thread ausgeführt. – ptr0x