Warum können Sie mit C # eine asynchrone Außerkraftsetzung durchführen?

16

Wenn Sie in C # eine Methode überschreiben, ist es zulässig, die Überschreibung asynchron auszuführen, wenn dies bei der ursprünglichen Methode nicht der Fall war. Dies scheint eine schlechte Form zu sein.

Das Beispiel, das mich dazu brachte, war das folgende: Ich wurde hinzugezogen, um bei einem Lasttestproblem zu helfen. Bei ungefähr 500 gleichzeitigen Benutzern würde der Anmeldevorgang in einer Umleitungsschleife unterbrochen. IIS protokollierte Ausnahmen mit der Meldung "Ein asynchrones Modul oder Handler wurde abgeschlossen, während ein asynchroner Vorgang noch ausstand". Einige async voidSuchanfragen ließen mich vermuten, dass jemand Missbrauch betrieben hatte , aber meine schnelle Suche in der Quelle konnte nichts finden.

Leider habe ich nach 'async \ svoid' (Regex-Suche) gesucht, als ich nach etwas ähnlichem wie 'async \ s [^ T]' hätte suchen sollen (vorausgesetzt, Task ist nicht vollständig qualifiziert ... Sie haben es verstanden).

Was ich später fand, war async override void onActionExecuting(...in einem Basiscontroller. Das musste natürlich das Problem sein, und das war es auch. Das Problem wurde behoben, indem es für den Moment synchronisiert wurde.

Zurück zur Frage: Warum können Sie eine Außerkraftsetzung als asynchron markieren, wenn der aufrufende Code sie niemals erwarten könnte?

Peter T. LaComb Jr.
quelle
Was genau hindert einen Anrufer daran, auf die überschriebene Methode zu warten? Ich sehe kein Hindernis.
Martin Maat
@MartinMaat Sie können nur auf zurückgegebene Methoden warten Task.
Derek Elkins hat SE
Vielleicht ist das ein guter Punkt, den ich nicht bemerkt hatte. Ich müsste das überprüfen, kann mich aber nicht an die VS-Warnung erinnern, nicht asynchrone Methoden aufzurufen, ohne abzuwarten.
Peter T. LaComb Jr.

Antworten:

16

Mit dem Schlüsselwort async kann die Methode die awaitSyntax innerhalb ihrer Definition verwenden. Ich kann awaitfür jede Methode, die einen TaskTyp zurückgibt, unabhängig davon, ob es sich um eine asynchrone Methode handelt.

voidIst ein zulässiger (wenn auch nicht empfohlener ) Rückgabetyp für eine asynchrone Methode. Warum sollte dies nicht zulässig sein? asyncAktiviert von außen nichts, was man ohne nicht machen könnte. Die Methode, mit der Sie Probleme haben, wurde möglicherweise so geschrieben, dass sie sich genauso verhält, ohne asynchron zu sein. Seine Definition wäre nur ausführlicher gewesen.

Anrufer, ein async Tist Verfahren ein normales Verfahren , dass zurückkehrt T(die begrenzt ist void, Taskoder Task<A>). Dass es sich um eine asynchrone Methode handelt, gehört nicht zur Schnittstelle. Beachten Sie, dass der folgende Code illegal ist:

interface IFoo {
    async void Bar();
}

Es (oder ein ähnlicher Code in einer abstrakten Klasse) erzeugt die folgende Fehlermeldung in VS2012:

Der Modifikator 'async' kann nur in Methoden mit einem Anweisungstext verwendet werden

Wenn ich habe eine Methode in einer Schnittstelle oder Elternklasse beabsichtigt typischerweise asynchron zu sein, kann ich nicht verwenden async, die miteinander zu kommunizieren. Wenn ich es mit der awaitSyntax implementieren wollte , müsste ich in der Lage sein, asynchrone Überschreibungsmethoden zu haben (im Fall der Elternklasse).

Derek Elkins verließ SE
quelle
1
Sie erwähnen overrideüberhaupt nicht, aber darum geht es in der Frage.
Nathan Tuggy
4
@ NathanTuggy Der springende Punkt der Antwort ist, dass asyncdie Schnittstelle einer Methode nicht geändert wird, sondern nur das, was in der Definition syntaktisch zulässig ist. Ob es sich also um eine Überschreibung handelt oder nicht, ist völlig irrelevant.
Derek Elkins verließ SE
1
Erklären Sie dies bitte , anstatt davon auszugehen, dass jeder bereits alles Relevante weiß.
Nathan Tuggy
2
@ NathanTuggy Ich glaube, ich habe es erklärt. Können Sie eine bestimmte Frage stellen, über die Sie verwirrt sind, oder stellen Sie sich vor, dass eine andere verwirrte Person dies tun würde? Das einzige, was ich hinzufügen kann, ist zu betonen, dass der asyncModifikator nur auf Implementierungen angewendet werden kann. Sie können eine Methode nicht als asynchron in einer Schnittstelle deklarieren, indem Sie beispielsweise unterstreichen, dass eine asynchrone Methode nicht Teil der Schnittstelle ist.
Derek Elkins verließ SE
5
Gib die Erklärung in die Antwort ein , meine ich. Das ist nicht das, was Kommentare auf lange Sicht bedeuten.
Nathan Tuggy
10

Der einzige Zweck des asynchronen Schlüsselworts besteht darin, das Warten innerhalb des Hauptteils dieser Funktion zu einem Schlüsselwort zu machen. Dies ist erforderlich, damit das Hinzufügen der Wartefunktion den vorhandenen Code nicht beschädigt. Microsoft hat beschlossen, die Option zum Abwarten einer Anmeldung zu verwenden. Für eine Funktion, die nicht als asynchron markiert ist, können Sie eine Variable mit dem Namen wait ohne Probleme definieren.

Daher ist Async nicht Teil der Signatur einer Funktion und hat im generierten IL-Code keine semantische Bedeutung. Der Compiler muss unbedingt wissen, wie die Funktion korrekt kompiliert wird. Außerdem wird der Compiler angewiesen, sicherzustellen, dass nur Task, Task <T> oder void zurückgegeben werden.

Eric Johnson
quelle