c# asynchronous async-await ctp

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; }