Acabo de recibir VS2012 y estoy tratando de manejarlo async
.
Digamos que tengo un método que obtiene algún valor de una fuente de bloqueo. No quiero bloquear la persona que llama del método. Podría escribir el método para tomar una devolución de llamada que se invoca cuando llega el valor, pero como estoy usando C # 5, decido hacer que el método sea asíncrono para que las personas que llaman no tengan que lidiar con devoluciones de llamada:
// 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();
});
}
Aquí hay un método de ejemplo que lo llama. Si PromptForStringAsync
no fuera asíncrono, este método requeriría anidar una devolución de llamada dentro de una devolución de llamada. Con async, puedo escribir mi método de esta manera muy natural:
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);
}
Hasta aquí todo bien. El problema es cuando llamo a GetNameAsync:
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
El punto GetNameAsync
es que es asíncrono. No quiero que se bloquee, porque quiero volver a MainWorkOfApplicationIDontWantBlocked lo antes posible y dejar que GetNameAsync haga lo suyo en segundo plano. Sin embargo, llamarlo de esta manera me da una advertencia del compilador en la GetNameAsync
línea:
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.
Soy perfectamente consciente de que "la ejecución del método actual continúa antes de que se complete la llamada". Ese es el punto del código asincrónico, ¿verdad?
Prefiero compilar mi código sin advertencias, pero no hay nada que "arreglar" aquí porque el código está haciendo exactamente lo que tengo la intención de hacer. Puedo deshacerme de la advertencia almacenando el valor de retorno de GetNameAsync
:
public static void DoStuff()
{
var result = GetNameAsync(); // supress warning
MainWorkOfApplicationIDontWantBlocked();
}
Pero ahora tengo un código superfluo. Visual Studio parece comprender que me vi obligado a escribir este código innecesario, ya que suprime la advertencia normal de "valor nunca utilizado".
También puedo deshacerme de la advertencia envolviendo GetNameAsync en un método que no es asíncrono:
public static Task GetNameWrapper()
{
return GetNameAsync();
}
Pero ese es un código aún más superfluo. Entonces tengo que escribir código que no necesito o tolerar una advertencia innecesaria.
¿Hay algo sobre mi uso de async que esté mal aquí?
GetNameAsync
proporcionar el nombre completo que fue proporcionado por el usuario (es decir Task<Name>
, en lugar de devolver un Task
? DoStuff
Entonces podría almacenar esa tarea, y ya sea await
que después el otro método, o incluso pasar la tarea a la otra método por lo que podría await
o Wait
en algún lugar dentro de ella de aplicación.
async
palabra clave.
PromptForStringAsync
, hace más trabajo del que necesita; solo devuelve el resultado deTask.Factory.StartNew
. Ya es una tarea cuyo valor es la cadena ingresada en la consola. No hay necesidad de esperar y devolver el resultado; hacerlo no agrega ningún valor nuevo.