await funciona pero llamando tarea.Resultado bloqueos / bloqueos


Tengo las siguientes cuatro pruebas y la última se cuelga cuando la corro, mi pregunta es por qué sucede esto:

[Test]
public void CheckOnceResultTest()
{
    Assert.IsTrue(CheckStatus().Result);
}

[Test]
public async void CheckOnceAwaitTest()
{
    Assert.IsTrue(await CheckStatus());
}

[Test]
public async void CheckStatusTwiceAwaitTest()
{
    Assert.IsTrue(await CheckStatus());
    Assert.IsTrue(await CheckStatus());
}

[Test]
public async void CheckStatusTwiceResultTest()
{
    Assert.IsTrue(CheckStatus().Result); // This hangs
    Assert.IsTrue(await CheckStatus());
}

private async Task<bool> CheckStatus()
{
    var restClient = new RestClient(@"https://api.test.nordnet.se/next/1");
    Task<IRestResponse<DummyServiceStatus>> restResponse = restClient.ExecuteTaskAsync<DummyServiceStatus>(new RestRequest(Method.GET));
    IRestResponse<DummyServiceStatus> response = await restResponse;
    return response.Data.SystemRunning;
}

Uso este método de extensión para restsharp RestClient :

public static class RestClientExt
{
    public static Task<IRestResponse<T>> ExecuteTaskAsync<T>(this RestClient client, IRestRequest request) where T : new()
    {
        var tcs = new TaskCompletionSource<IRestResponse<T>>();
        RestRequestAsyncHandle asyncHandle = client.ExecuteAsync<T>(request, tcs.SetResult);
        return tcs.Task;
    }
}
public class DummyServiceStatus
{
    public string Message { get; set; }
    public bool ValidVersion { get; set; }
    public bool SystemRunning { get; set; }
    public bool SkipPhrase { get; set; }
    public long Timestamp { get; set; }
}

¿Por qué se cuelga la última prueba?

Author: Johan Larsson, 2013-06-22

5 answers

Te encuentras con la situación de bloqueo estándar que describo en mi blog y en un artículo de MSDN: el método async está intentando programar su continuación en un hilo que está siendo bloqueado por la llamada a Result.

En este caso, su SynchronizationContext es el utilizado por NUnit para ejecutar async void métodos de prueba. Yo intentaría usar async Task métodos de prueba en su lugar.

 73
Author: Stephen Cleary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-22 08:30:52

Adquiriendo un valor a través de un método asincrónico:

var result = Task.Run(() => asyncGetValue()).Result;

Llamando sincrónicamente a un método asíncrono

Task.Run( () => asyncMethod()).Wait();

No se producirán problemas de bloqueo debido al uso de la Tarea.Ejecutar.

 170
Author: Herman Schoenfeld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-07 00:46:51

Puedes evitar un punto muerto añadiendo ConfigureAwait(false) a esta línea:

IRestResponse<DummyServiceStatus> response = await restResponse;

=>

IRestResponse<DummyServiceStatus> response = await restResponse.ConfigureAwait(false);

He descrito esta trampa en mi entrada de blog Trampas de async / await

 14
Author: Vladimir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-20 15:05:49

Está bloqueando la interfaz de usuario mediante Task.Propiedad Resultado. En La documentación de MSDN han mencionado claramente que,

"La propiedad Result es una propiedad de bloqueo. Si intentas acceder a él antes de que finalice su tarea, el hilo que está activo actualmente es bloqueado hasta que la tarea se complete y el valor esté disponible. En la mayoría casos, debe acceder al valor usando Await o await en lugar de acceso a la propiedad directamente."

La mejor solución para este escenario sería eliminar ambos await & async de los métodos y usar solo Tarea donde está devolviendo el resultado. No arruinará tu secuencia de ejecución.

 7
Author: Dark Knight,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-31 23:15:56

Si no recibe devoluciones de llamada o el control se cuelga, después de llamar a la Función Async Service/API. Tienes que configurar Contexto para devolver el resultado en el mismo contexto llamado. Use TestAsync ().Por lo tanto, no es necesario que el usuario tenga acceso a la información.]}

Se enfrentará a este problema solo en aplicaciones Web, pero no en Static void main

 2
Author: Mayank Pandit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-03 11:07:18