aguarda el trabajo pero llama a task.Result cuelga / deadlocks

Tengo las siguientes cuatro pruebas y la última se cuelga cuando la ejecuto, 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 CheckStatus() { var restClient = new RestClient(@"https://api.test.nordnet.se/next/1"); Task<IRestResponse> restResponse = restClient.ExecuteTaskAsync(new RestRequest(Method.GET)); IRestResponse response = await restResponse; return response.Data.SystemRunning; } 

Yo uso este método de extensión para restClient restsharp :

 public static class RestClientExt { public static Task<IRestResponse> ExecuteTaskAsync(this RestClient client, IRestRequest request) where T : new() { var tcs = new TaskCompletionSource<IRestResponse>(); RestRequestAsyncHandle asyncHandle = client.ExecuteAsync(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?

Te encuentras con la situación estándar de punto muerto que describo en mi blog y en un artículo de MSDN : el método async está intentando progtwigr 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 métodos de prueba de async void . Intentaría usar métodos de prueba async Task lugar.

Adquirir un valor a través de un método asíncrono:

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

Llamando Syncrono a un método asíncrono

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

No se producirán problemas de interlocking debido al uso de Task.Run.

Puede evitar el interlocking agregando ConfigureAwait(false) a esta línea:

 IRestResponse response = await restResponse; 

=>

 IRestResponse response = await restResponse.ConfigureAwait(false); 

Describí este error en mi publicación de blog. Errores de async / await

Está bloqueando la UI mediante la propiedad Task.Result. En MSDN Documentation , han mencionado claramente que,

“La propiedad Result es una propiedad de locking. Si intenta acceder antes de que su tarea finalice, la secuencia actualmente activa se bloquea hasta que la tarea finalice y el valor esté disponible. En la mayoría de los casos, debe acceder al valor usando Await. o espera en lugar de acceder a la propiedad directamente “.

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

Si no recibe devoluciones de llamada o el control se cuelga, después de llamar a la función de servicio / API Async. Debe configurar Contexto para devolver el resultado en el mismo contexto llamado. Use TestAsync (). ConfigureAwait (continueOnCapturedContext: false);

Te enfrentarás a este problema solo en aplicaciones web, pero no en Static void main