asíncrono espera regreso Tarea

131

¿Alguien puede explicar qué significa esto en un método sincrónico? Si trato de cambiar el método a asyncVS, entonces me quejo.

Esto funciona:

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

Esto no funciona:

public async Task MethodName()
{
     return Task.FromResult<object>(null);
}

Básicamente, me gustaría saber qué significa exactamente esto: Task.FromResult<object>(null);

David Dury
fuente
1
Además, lea MSDN: msdn.microsoft.com/en-us/library/hh194922(v=vs.110).aspx .
Patrick Hofman
@LB hmm eso funciona! ¡Pero también si solo return;trabajo también ...!
David Dury el
2
"no funciona" no proporciona una muy buena descripción de lo que no funciona. ¿Cuál es el mensaje de error que recibe?
John Koerner
@JohnKoerner Creo que es bastante obvio que el compilador podría darle el mismo error que si intentara devolver un valor en una voidfunción.
binki

Respuestas:

236

asyncLos métodos son diferentes a los métodos normales. Lo que devuelva de los asyncmétodos está envuelto en un Task.

Si no devuelve ningún valor (nulo), se envolverá Task, si devuelve int, se envolverá Task<int>y así sucesivamente.

Si su método asíncrono necesita retornar int, marcaría el tipo de retorno del método como Task<int>y devolverá sin formato intel Task<int>. Compilador convertirá el intque Task<int>para usted.

private async Task<int> MethodName()
{
    await SomethingAsync();
    return 42;//Note we return int not Task<int> and that compiles
}

Del mismo modo, cuando devuelva Task<object>el tipo de retorno de su método debe serTask<Task<object>>

public async Task<Task<object>> MethodName()
{
     return Task.FromResult<object>(null);//This will compile
}

Como su método está regresando Task, no debería devolver ningún valor. De lo contrario, no se compilará.

public async Task MethodName()
{
     return;//This should work but return is redundant and also method is useless.
}

Tenga en cuenta que el método asíncrono sin una awaitdeclaración no lo es async.

Sriram Sakthivel
fuente
1
Para mí, este tipo de retorno no funciona (supongo que estoy haciendo algo mal). Ejemplo de tarea asíncrona estática <string> DoStuff () {... = await SomeMethodAsync (); devolver "valor de cadena"; } .. var x = DoStuff (); Pero esta x es con el tipo "Tarea <cadena>", no con el tipo "cadena" ... ¿Por qué es así?
Prokurors
3
@Prokurors También debes esperar DoStuff(). Por ejemplo:var x = await DoStuff();
Sriram Sakthivel
55
Debería serreturn await Task.FromResult<object>(null);
sandeep talabathula
@sandeeptalabathula que equivale a devolver nulo
Sriram Sakthivel
2
@ProfK Task.WhenAnyes un ejemplo.
Servy
55

Debe usar la palabra clave await cuando use async y el tipo de retorno de su función debe ser genérico. Aquí hay un ejemplo con valor de retorno:

public async Task<object> MethodName()
{
    return await Task.FromResult<object>(null);
}

Aquí hay un ejemplo sin valor de retorno:

public async Task MethodName()
{
    await Task.CompletedTask;
}

Lee esto:

TPL: http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx y tareas: http://msdn.microsoft.com/en-us/library/system.threading .tareas (v = vs.110) .aspx

Asíncrono: http://msdn.microsoft.com/en-us/library/hh156513.aspx Aguarde: http://msdn.microsoft.com/en-us/library/hh156528.aspx

Mayor
fuente
9
Puede regresar nulldirectamente en lugar de esperar una tarea ficticia.
Lee
55
@Lee, pero si haces eso, el compilador se queja (da una advertencia) de que el asyncmétodo se ejecutará de forma asincrónica con una sugerencia de usar la awaitpalabra clave en algún lugar del método. Sugiero usar return Task.FromResult((object)null);y eliminar la asyncpalabra clave para reducir el ruido de advertencia del compilador.
binki
Sí, he intentado simplemente usar returnen una tarea, pero la tarea sigue ejecutándose, porque returnno está devolviendo unTask
Turner Bass
30

Agregar la palabra clave asíncrona es simplemente azúcar sintáctica para simplificar la creación de una máquina de estados. En esencia, el compilador toma su código;

public async Task MethodName()
{
     return null;
}

Y lo convierte en;

public Task MethodName()
{
     return Task.FromResult<object>(null);
}

Si su código tiene alguna awaitpalabra clave, el compilador debe tomar su método y convertirlo en una clase para representar la máquina de estado requerida para ejecutarlo. En cada awaitpalabra clave, el estado de las variables y la pila se conservarán en los campos de la clase, la clase se agregará como un enlace de finalización a la tarea que está esperando y luego regresará.

Cuando esa tarea se complete, su tarea se ejecutará nuevamente. Por lo tanto, se agrega un código adicional en la parte superior del método para restaurar el estado de las variables y saltar a la siguiente losa de su código.

Consulte ¿Qué genera async & await? por un sangriento ejemplo.

Este proceso tiene mucho en común con la forma en que el compilador maneja los métodos iteradores con declaraciones de rendimiento.

Jeremy Lakeman
fuente
2

Esta es una tarea que devuelve una tarea de tipo String (función anónima de C # o, en otras palabras, una delegación se usa 'Func')

    public static async Task<string> MyTask()
    {
        //C# anonymous AsyncTask
        return await Task.FromResult<string>(((Func<string>)(() =>
        {
            // your code here
            return  "string result here";

        }))());
    }
Adel Mourad
fuente
1
Cuando publique código como respuesta, incluya alguna explicación de lo que está demostrando. En este caso, está agregando una respuesta a una pregunta anterior que ya tiene varias respuestas. Agregue una o dos oraciones que describan lo que está demostrando su nueva respuesta, que ya no se mostró en las otras respuestas. No digo que haya algo mal con su respuesta, solo le pido que ayude a otros poniendo en palabras lo que está mostrando con su código.
ToolmakerSteve
0

Para obtener respuestas adecuadas de los métodos asincrónicos, debe esperar mientras llama a esos métodos de tarea. Eso esperará a volver a convertirlo al tipo de valor devuelto en lugar del tipo de tarea.

Por ejemplo, var content = await StringAsyncTask (

donde public async Task < String > StringAsyncTask ())

abhiroop mukherjee
fuente