c#¿Puede un "método de tarea" también ser un método "asíncrono"?
asynchronous async-await (2)
¿Puede un "método de tarea" también ser un método "asíncrono"?
Sí, puede ser, simplemente cambiando la firma del método a public async static Task<Task<String>> LongTaskAAsync()
ya que es, lo que devolverá.
Si usa la palabra clave async
, el tiempo de ejecución ajustará el tipo que devuelve a una tarea para habilitar la asincronía. Digamos que si devuelve una string
, el tiempo de ejecución la incluirá en una Task<string>
. int
irá Task<int>
y Task<string>
irá Task<Task<string>>
. Vea esta aplicación de consola para borrar:
public class Program
{
public static void Main(string[] args)
{
// start the main procedure asynchron
Task.Run(() => DoIt()).Wait();
}
// for async support since the static main method can''t be async
public static async void DoIt()
{
Program p = new Program();
// use the methods
string s = await p.GetString();
int i = await p.GetInt();
Task<string> tsk = await p.GetTaskOfString();
// just to prove the task works:
// C# 5
string resultFromReturnedTask = await tsk;
// C# 4
string resultFromReturnedTask2 = tsk.Result;
}
public async Task<string> GetString()
{
return "string";
}
public async Task<int> GetInt()
{
return 6;
}
public async Task<Task<string>> GetTaskOfString()
{
return Task.Run(() => "string");
}
}
Estoy tratando de obtener la mano del nuevo CTP asincrónico y probablemente me confundo aquí. Puedo tener este "método de tarea", sin ningún problema:
public static Task<String> LongTaskAAsync() {
return Task.Run(() => {
return("AAA");
});
}
Pero, ¿y si necesito la tarea para ejecutar otra tarea, puedo marcarla como "asincrónica" y usar "esperar"? Intenté esto:
public async static Task<String> LongTaskAAsync() {
await Task.Delay(2000);
return Task.Run(() => {
return("AAA");
});
}
Pero luego misteriosamente aparece este error del compilador: dado que este es un método asíncrono, la expresión de retorno debe ser de tipo ''cadena'' en lugar de Task<string>
¿Que me estoy perdiendo aqui?
Miguel
Es posible que desee leer mi publicación intro async
/ await
.
Los valores async
métodos async
se envuelven en una Task<TResult>
. Del mismo modo, await
desenvolver esos valores de retorno:
public static async Task<String> LongTaskAAsync() {
await Task.Delay(2000);
return await Task.Run(() => {
return("AAA");
});
}
El razonamiento detrás de esto se describe en mi Async "¿Por qué las palabras clave funcionan así? " Preguntas frecuentes no oficiales .
PD También puede usar Task.FromResult
para pruebas simples como esta.
Editar: si desea crear y devolver el objeto Task
sí, entonces el método no debe ser async
. Un patrón algo común es tener un método public
no async
que llame a la parte async
solo si es necesario.
Por ejemplo, algún tipo de caché asíncrona: si el objeto está en el caché, devuélvalo inmediatamente; de lo contrario, créelo de manera asíncrona, agréguelo al caché y devuélvalo (este es un código de ejemplo, no seguro para subprocesos):
public static Task<MyClass> GetAsync(int key)
{
if (cache.Contains(key))
return Task.FromResult(cache[key]);
return CreateAndAddAsync(key);
}
private static async Task<MyClass> CreateAndAddAsync(int key)
{
var result = await CreateAsync(key);
cache.Add(key, result);
return result;
}