Ich habe gerade VS2012 bekommen und versucht, es in den Griff zu bekommen async
.
Angenommen, ich habe eine Methode, die einen Wert von einer blockierenden Quelle abruft. Ich möchte nicht, dass der Aufrufer der Methode blockiert. Ich könnte die Methode schreiben, um einen Rückruf anzunehmen, der beim Eintreffen des Werts aufgerufen wird. Da ich jedoch C # 5 verwende, entscheide ich mich, die Methode asynchron zu machen, damit Anrufer sich nicht mit Rückrufen befassen müssen:
// contrived example (edited in response to Servy's comment)
public static Task<string> PromptForStringAsync(string prompt)
{
return Task.Factory.StartNew(() => {
Console.Write(prompt);
return Console.ReadLine();
});
}
Hier ist eine Beispielmethode, die es aufruft. Wenn dies PromptForStringAsync
nicht asynchron wäre, müsste für diese Methode ein Rückruf in einen Rückruf verschachtelt werden. Mit Async kann ich meine Methode auf ganz natürliche Weise schreiben:
public static async Task GetNameAsync()
{
string firstname = await PromptForStringAsync("Enter your first name: ");
Console.WriteLine("Welcome {0}.", firstname);
string lastname = await PromptForStringAsync("Enter your last name: ");
Console.WriteLine("Name saved as '{0} {1}'.", firstname, lastname);
}
So weit, ist es gut. Das Problem ist , wenn ich anrufen GetNameAsync:
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
Der springende Punkt GetNameAsync
ist, dass es asynchron ist. Ich möchte nicht, dass es blockiert wird, da ich so schnell wie möglich zu MainWorkOfApplicationIDontWantBlocked zurückkehren und GetNameAsync im Hintergrund ausführen lassen möchte. Wenn ich es jedoch so nenne, erhalte ich eine Compiler-Warnung in der GetNameAsync
Zeile:
Warning 1 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
Mir ist völlig bewusst, dass "die Ausführung der aktuellen Methode fortgesetzt wird, bevor der Aufruf abgeschlossen ist". Das ist der Punkt des asynchronen Codes, richtig?
Ich bevorzuge es, meinen Code ohne Warnungen zu kompilieren, aber hier gibt es nichts zu "reparieren", da der Code genau das tut, was ich beabsichtige. Ich kann die Warnung entfernen, indem ich den Rückgabewert von GetNameAsync
:
public static void DoStuff()
{
var result = GetNameAsync(); // supress warning
MainWorkOfApplicationIDontWantBlocked();
}
Aber jetzt habe ich überflüssigen Code. Visual Studio scheint zu verstehen, dass ich gezwungen war, diesen unnötigen Code zu schreiben, da er die normale Warnung "Wert nie verwendet" unterdrückt.
Ich kann die Warnung auch entfernen, indem ich GetNameAsync in eine Methode einbinde, die nicht asynchron ist:
public static Task GetNameWrapper()
{
return GetNameAsync();
}
Aber das ist noch mehr überflüssig Code. Ich muss also Code schreiben, den ich nicht brauche oder eine unnötige Warnung toleriere.
Gibt es etwas an meiner Verwendung von Async, das hier nicht stimmt?
GetNameAsync
den vollständigen Namen zur Verfügung zu stellen, die vom Benutzer (dh zur Verfügung gestellt wurde Task<Name>
, und nicht nur eine Rückkehr Task
? DoStuff
Könnte dann speichern , diese Aufgabe, und entweder await
es nach dem anderen Verfahren oder sogar passiert die Aufgabe zu , dass andere Methode, damit es könnte await
oder Wait
es irgendwo innerhalb seiner Implementierung.
async
Schlüsselwort.
PromptForStringAsync
erledigen Sie mehr Arbeit als nötig. Geben Sie einfach das Ergebnis von zurückTask.Factory.StartNew
. Es ist bereits eine Aufgabe, deren Wert die in die Konsole eingegebene Zeichenfolge ist. Es besteht keine Notwendigkeit, darauf zu warten und das Ergebnis zurückzugeben. Dies bringt keinen neuen Wert.