Run async method in overridden void

I am currently creating an ASP.NET MVC application. I am trying to add elements to the ViewBag property for all pages of my site. To do this, I created a basic controller, to which all my site controllers are inherited.

To add to the ViewBag, I redefined the OnActionExecuting method: protected override void OnActionExecuting(ActionExecutingContext filterContext)

I know that OnActionExecuting methods for MVC5 are not async, so I ran into this problem. I need to be able to call some form of the following code to retrieve the latest elements and put them in a ViewBag:

 IList<PlaceListItemViewModel> places = await GetLatestPlaces(3); ViewBag.FooterLatestPlaces = places; 

Using GetLatestPlaces(3).Result just causes a dead end, so this is not an option.

Can anyone give me an opportunity on how to achieve this. It also should not override the OnActionExecuting method, if there is another way to add elements to the ViewBag for each page (except for calling the code from each separate action on each controller), I am open to using this method.

Unfortunately, the GetLatestPlaces method cannot be asynchronous because it uses the MongoDB 2.0 driver, which is completely asynchronous.

+6
source share
3 answers

There are two main ways to achieve the desired result:

  • Use ConfigureAwait(false) in your async library. In your case, you must do this inside the GetLatestPlaces() method.
  • Call the async method on another thread so as not to block the current context. So your code will look like this:

     IList<PlaceListItemViewModel> places = Task.Run(async () => await GetLatestPlaces(3)).Result; 

For more information, see Stephen Cleary's excellent blog post .

+10
source

The cause of the deadlock is the captured synchronous context. You can avoid this var res = await GetLatestPlaces(3).ConfigureAwait(false);

0
source

Here is a method that allows you to synchronously invoke asynchronous usage methods for performance overhead and overhead:

 public static T GetResult<T>(Func<Task<T>> func) { var syncContext = SynchronizationContext.Current; SynchronizationContext.SetSynchronizationContext(null); var task = func(); SynchronizationContext.SetSynchronizationContext(syncContext); return task.Result; } 

So you would call

 var places = GetResult(() => GetLatestPlaces(3)); 

However, be careful, as the current SynchronizationContext not fixed, any context associated with it does not flow into the task. In your example, HttpContext.Current will not be available in GetLatestPlaces() .

0
source

Source: https://habr.com/ru/post/987968/


All Articles