2012-07-06 13 views
8

Estoy usando Visual Studio 2012 RC con .Net 4.5 y ASP MVC 4 RC. Se cuelga cada vez que uso asincronización. El método de acción del controlador usa asincronismo pero no es un método de controlador asíncrono.ASP.Net MVC 4 controlador cuelga cada vez que se utiliza asíncrono

No se registraron errores ni se lanzaron excepciones, pero el navegador muestra "Esperando www.myweb.local" para siempre.

// Simplest possible async 
public class Waiter 
{ 
    public async Task<int> GetValue() 
    { 
     await Task.Yield(); 
     return await Task.Factory.StartNew(() => 42); 
    } 
} 

// simplest possible controller that uses the async 
public class HomeController : Controller 

    public ActionResult Index() 
    { 
     var waiter = new Waiter(); 
     var resultTask = waiter.GetValue(); 
     int result = resultTask.Result; 

     // it never gets here 
     return View(); 
    } 
} 

he hecho las cosas que se señalan in this answer, y todavía no funciona. es decir. El web.config contiene

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/> 

Y las palabras mágicas son await Task.Yield(); en el método asíncrono.

el .NET Framework versión es 4.5.50501. He observado este comportamiento en IIS Express y en IIS 6.0.

Intenté aplicar la "actualización de julio de 2012" a VS2012, pero eso no lo solucionó.

This answer suggests que puede ser debido a que la tarea ya se ha completado cuando lo espero, sin embargo, si ese fuera el caso, esto debería funcionar y no lo hace:

public class Waiter 
{ 
    public async Task<int> GetValue() 
    { 
     await Task.Yield(); 
     return await Task.Factory.StartNew(() => 
      { 
       Thread.Sleep(1500); 
       return 42; 
      }); 
    } 
} 

Un par de personas han sugerido que ConfigureAwait(false) se necesita, pero este código no funciona bien:

public async Task<int> GetValue() 
    { 
     var task = new Task<int>(() => 42); 
     return await task.ConfigureAwait(false); 
    } 

la siguiente Cómo funciona con el motor de vista de la maquinilla de afeitar, pero no con chispa. Seguramente debería haber una manera de hacer que el otro escenario funcione también? ¿No se pueden usar las tareas asincrónicas dentro del código síncrono?

public class Waiter 
{ 
    public async Task<int> GetValue() 
    { 
     return await Task.Factory.StartNew(() => 42); 
    } 
} 

public class HomeController : Controller 
{ 
    public async Task<ActionResult> IndexAsync() 
    { 
     await Task.Yield(); 
     var waiter = new Waiter(); 
     int result = await waiter.GetValue(); 

     return View(); 
    } 
} 

sé que es esto no se libera el software, pero los CR de Microsoft son por lo general bastante estable, por lo que me sorprende que se produce un error, y no de una manera inútil.

+2

Lo siento si me falta algo, pero ¿por qué tener el bloque índice a través de acceso a la propiedad en lugar de marcar resultado que esperan ser asíncrono y el uso de allí? Si eso es intencional, es posible que deba usar ConfigureAwait (falso) para que la continuación no se vuelva a programar en el mismo hilo. –

+0

Estoy probando portar un sitio web existente a .Net 4.5. Utiliza el motor de vista de chispa.Quería trabajar de manera asíncrona antes de lidiar con los controladores asíncronos y si la chispa podía manejar la Tarea o no (mi impresión inicial era no). Pero independientemente de si podría hacer eso o no, este escenario debería funcionar. – Anthony

+0

¿Por qué se deriva de AsyncController? Eso no es necesario. Ver mi muestra asíncrona http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4 – RickAndMSFT

Respuesta

1

he tenido asíncrono trabajando en la beta muy bien. No lo he probado, pero supongo que es porque el método de tu controlador no es asincrónico. Cámbielo por:

public async Task<ActionResult> IndexAsync() 
{ 
    var waiter = new Waiter(); 
    int result = await waiter.GetValue(); 

    // it never gets here 
    return View(); 
} 
+0

Si es "porque el método del controlador no es asincrónico", ¿está diciendo que usar tareas asíncronas nunca funcionará en el código de sincronización? De lo contrario, debería haber una forma de hacer que este código funcione. – Anthony

+0

OK, editado para agregar la Tarea mientras yo digerir eso ... –

+0

Así que GetValue() no se completa entonces ... No puedo pensar en una razón obvia para sacar eso de mi cabeza de lo que tienes y estoy en el tren ahora mismo! Echaré un vistazo más adelante si nadie me pega. –

9

Estás provocando un interbloqueo, just like this question.

sugerencia de James Manning es correcta, pero hay que await el resultado de ConfigureAwait, así:

public async Task<int> GetValue() 
{ 
    var task = new Task<int> (() => 42); 
    return await task.ConfigureAwait(false); 
} 

En general, la mezcla de código síncrona y asíncrona es una idea realmente mala a menos que realmente sepa lo que' re haciendo Hacer que la acción del controlador sea asíncrona sería mucho mejor.

+1

Estoy de acuerdo, sobre todo porque ahora es tan fácil hacer que los métodos del controlador sean asíncronos. Aunque puedo ver algunos casos (muy * muy * raros) donde podría tener sentido ejecutar algunas tareas en paralelo dentro de un controlador síncrono. Siempre vale la pena leer este artículo antes de dejarse llevar por los controladores asíncronos también: http://blog.stevensanderson.com/2010/01/25/measuring-the-performance-of-asynchronous-controllers/ –

+0

Seguramente cualquier programa C# que utiliza la palabra clave async "mezcla el código síncrono y asíncrono"? Usar un controlador Async solo significa que el límite está en el marco. – Anthony

+0

En cuanto a "ahora es tan fácil hacer que los métodos del controlador sean asíncronos", no si tiene muchas vistas existentes usando el motor de chispa. – Anthony

Cuestiones relacionadas