Is it possible to create a custom RenderMvcController, but have it be async?
I've created my own RenderMvcController called CustomRenderMvcController and set it up as the default RenderMvcController. To add functions to this controller (I want to use a different default RenderModel) I have to override the Index() method.
Herein lies my problem. This method is not async, so overriding it always gives me a non async method. Any async action I try to perform in this method (for instance getting something from a remote url) always has to use the sync variation.
Am I doing something wrong here or is this just how it is?
I'm afraid not. As far as I know, when using a custom RenderMvcController you're stuck to either using the synchronous variant of a method or, if this is not available, use something like Stephen Cleary's AsyncEx to call awaitable methods from a synchronous method.
Why not just use the methods on Task to wait in the controller?
public class SomeRenderController : RenderMvcController
{
public override ActionResult Index(RenderModel model)
{
var mightTimeOutTask = some.AsyncMethod();
mightTimeOutTask.Wait(TimeSpan.FromSeconds(10)); // Waits until done or continues at 10
// TODO: Handle timeouts
var value = mightTimeOutTask.Result; // .Result blocks until done
// OR
var prettyQuickResult = some.AsyncMethod().Result; // .Result blocks until done
return View();
}
}
Yeah, I haven't really been able to figure out exactly when it deadlocks and when it doesn't. I'm certain I've run into deadlock situations in the past, but seamingly similar situations wouldn't deadlock.
So now to be safe I generally just wrap it in an AsyncEx.Run() wrapper when calling async methods from synchronous methods, which to be frank, doesn't really happens all that often anymore these days.
Async RenderMvcController
Is it possible to create a custom RenderMvcController, but have it be async?
I've created my own RenderMvcController called CustomRenderMvcController and set it up as the default RenderMvcController. To add functions to this controller (I want to use a different default RenderModel) I have to override the Index() method.
Herein lies my problem. This method is not async, so overriding it always gives me a non async method. Any async action I try to perform in this method (for instance getting something from a remote url) always has to use the sync variation.
Am I doing something wrong here or is this just how it is?
Did you find a resolution to this? We are potentially facing the same issue.
I'm afraid not. As far as I know, when using a custom RenderMvcController you're stuck to either using the synchronous variant of a method or, if this is not available, use something like Stephen Cleary's AsyncEx to call awaitable methods from a synchronous method.
See here for more info https://github.com/StephenCleary/AsyncEx
Or get it from Nuget https://www.nuget.org/packages/Nito.AsyncEx/
Ofcourse you'll lose the benefits of async mehods, but at least it works.
Why not just use the methods on Task to wait in the controller?
In ASP.NET you should really try to avoid using the .Wait() methods or .Result property of tasks as they are prone to cause deadlocks.
See the blog below (incidentally also from the same Stephen) that explains why:
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
I see. Never knew that. Although none of my stuff have ever deadlocked.
However, as he states in his blog, adding .ConfigureAwait(false) to the second layer down should make everything safe, so my example still holds. ;)
Yeah, I haven't really been able to figure out exactly when it deadlocks and when it doesn't. I'm certain I've run into deadlock situations in the past, but seamingly similar situations wouldn't deadlock.
So now to be safe I generally just wrap it in an AsyncEx.Run() wrapper when calling async methods from synchronous methods, which to be frank, doesn't really happens all that often anymore these days.
It probably deadlocks with larger loads than we currently have where we've done this.
I'll start adding ConfigureAwait if I do this again and hope I'm in the green. :)
is working on a reply...