jeudi 10 avril 2014

c# - exécution de méthode d'action de contrôleur MVC asynchrone sans attendre à 'attendre' - Stack Overflow


I am using MVC 4 along with .NET 4.5. I wish to build an asynchronous controller leveraging the new TAP (async await). I have inherited this controller from Controller and not AsyncContoller, since I am using task-based asynchronicity, not event-based asynchronicity.


I have two action methods - one to perform an operation synchronously, and another to perform the same operation asynchronously. I also have two submit buttons in the form in my View, one for each action method.


Here is the code for both the methods:


Synchronous:


[HttpPost]
public ActionResult IndexSync(FormCollection formValues)
{
int Min = Int32.Parse(formValues["txtMin"]);
int Count = Int32.Parse(formValues["txtCount"]);
string Primes;
DateTime started = DateTime.Now;
using (BackendServiceReference.ServiceClient service = new ServiceClient())
{
Primes = service.GetPrimesServiceMethod(Min, Count);
}
DateTime ended = DateTime.Now;
TimeSpan serviceTime = ended - started;
ViewBag.ServiceTime = serviceTime;
ViewBag.Primes = Primes;

return View("Index");
}

Asynchronous:


[HttpPost]
public async Task<ActionResult> IndexAsync(FormCollection formValues)
{
int Min = Int32.Parse(formValues["txtMin"]);
int Count = Int32.Parse(formValues["txtCount"]);
string Primes;
Task<string> PrimesTask;
DateTime started = DateTime.Now;
using (BackendServiceReference.ServiceClient service = new ServiceClient())
{
PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count);
}
DateTime ended = DateTime.Now;
TimeSpan serviceTime = ended - started;
ViewBag.ServiceTime = serviceTime;
Primes = await PrimesTask;
ViewBag.Primes = Primes;

return View("Index");
}

In the async method, I expect DateTime ended = DateTime.Now to execute immediately after the service method is called, while the time-consuming service method executes asynchronously in the background.


However, this does not happen, and the execution 'waits' when the service method is called, instead of waiting where Primes = await PrimesTask happens.


Is there anything I have missed?


A nudge in the right direction would be appreciated.




I suspect that it is actually blocking in ServiceClient.Dispose.


To resolve this, extend the using block to include your await:


using (BackendServiceReference.ServiceClient service = new ServiceClient())
{
PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count);
DateTime ended = DateTime.Now;
TimeSpan serviceTime = ended - started;
ViewBag.ServiceTime = serviceTime;
Primes = await PrimesTask;
}
ViewBag.Primes = Primes;


I am using MVC 4 along with .NET 4.5. I wish to build an asynchronous controller leveraging the new TAP (async await). I have inherited this controller from Controller and not AsyncContoller, since I am using task-based asynchronicity, not event-based asynchronicity.


I have two action methods - one to perform an operation synchronously, and another to perform the same operation asynchronously. I also have two submit buttons in the form in my View, one for each action method.


Here is the code for both the methods:


Synchronous:


[HttpPost]
public ActionResult IndexSync(FormCollection formValues)
{
int Min = Int32.Parse(formValues["txtMin"]);
int Count = Int32.Parse(formValues["txtCount"]);
string Primes;
DateTime started = DateTime.Now;
using (BackendServiceReference.ServiceClient service = new ServiceClient())
{
Primes = service.GetPrimesServiceMethod(Min, Count);
}
DateTime ended = DateTime.Now;
TimeSpan serviceTime = ended - started;
ViewBag.ServiceTime = serviceTime;
ViewBag.Primes = Primes;

return View("Index");
}

Asynchronous:


[HttpPost]
public async Task<ActionResult> IndexAsync(FormCollection formValues)
{
int Min = Int32.Parse(formValues["txtMin"]);
int Count = Int32.Parse(formValues["txtCount"]);
string Primes;
Task<string> PrimesTask;
DateTime started = DateTime.Now;
using (BackendServiceReference.ServiceClient service = new ServiceClient())
{
PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count);
}
DateTime ended = DateTime.Now;
TimeSpan serviceTime = ended - started;
ViewBag.ServiceTime = serviceTime;
Primes = await PrimesTask;
ViewBag.Primes = Primes;

return View("Index");
}

In the async method, I expect DateTime ended = DateTime.Now to execute immediately after the service method is called, while the time-consuming service method executes asynchronously in the background.


However, this does not happen, and the execution 'waits' when the service method is called, instead of waiting where Primes = await PrimesTask happens.


Is there anything I have missed?


A nudge in the right direction would be appreciated.



I suspect that it is actually blocking in ServiceClient.Dispose.


To resolve this, extend the using block to include your await:


using (BackendServiceReference.ServiceClient service = new ServiceClient())
{
PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count);
DateTime ended = DateTime.Now;
TimeSpan serviceTime = ended - started;
ViewBag.ServiceTime = serviceTime;
Primes = await PrimesTask;
}
ViewBag.Primes = Primes;

0 commentaires:

Enregistrer un commentaire