0

I am using the answer here (https://stackoverflow.com/a/2759898) to render view as string.

I am new to async await thing. Just need to know if the following code will actually release the resources until the view is rendered? Just assume that my view will take 5 seconds to render.

public async Task<string> RenderViewToString(string viewName, object model)
{
  ViewData.Model = model;
  using (var sw = new StringWriter())
  {
    return await Task.Run(() =>
    {
      var razor = new RazorViewEngine();
      var viewResult = razor.FindView(ControllerContext, viewName, null, false);
      var viewContext = new ViewContext(ControllerContext, viewResult.View,
      ViewData, TempData, sw);
      viewResult.View.Render(viewContext, sw);
      viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
      return sw.GetStringBuilder().ToString();
    });
  }
}

P.S. Don't ask me why my views would take time to render. Although it is not a recommended practice BUT for this particular instance I have to call few web services in a view and create json output.

Community
  • 1
  • 1
user3219798
  • 333
  • 6
  • 14

3 Answers3

2

No. What this is doing is it's actually getting another thread from the ASP.NET thread pool to run the body of Task.Run(). During Task.Run()'s execution, the request thread is returned to the thread pool. And once Task.Run() finishes, it returns that thread and gets one to finish the request. All this code is doing is adding work... it's actually making matters worse.

If the views are calling web services, see if you can call the web services asynchronously. That's where async/await would increase efficiency.

Anthony Chu
  • 37,170
  • 10
  • 81
  • 71
  • Actually when the Task.Run is executing the thread is returned to the pool (that's what i want). I am unsure, If in a normal case, thread will be dedicated to the VIEW for 5 seconds (if view takes 5 seconds to complete)? – user3219798 Feb 21 '14 at 04:45
  • Yes, the request thread is returned to the pool, but it's pulling another thread from the same pool to do the work in `Task.Run()` and it'll hang onto it until completion, then return that to the pool and finally getting a thread to finish the request. You're not gaining anything compared to just hanging on to the request thread for the entire request. In fact, it's worse because of the overhead of swapping threads. It makes the app less scalable and less performant. – Anthony Chu Feb 21 '14 at 04:59
  • Can you please suggest how to release all the threads and get notified when the ViewResult is complete? – user3219798 Feb 21 '14 at 05:03
  • [There is no solution to this via Async because the work being done is CPU intensive, it's not waiting on an IO Completion port](http://blog.stephencleary.com/2014/04/a-tour-of-task-part-0-overview.html). – Erik Philips Jan 30 '17 at 17:21
1

You are not following the MVC pattern if your views are calling Web Services - the time required to "render" your views should not include the time it takes to make the web-service calls - you should make all these in the controller and pass the finalised Model with all the web services results/data to the view - then there's no concern about holding onto views or other resources...

Additionally there's no logical reason for even having a view when the result is Json - you should just have a controller that returns a JsonResult.

Rob
  • 10,004
  • 5
  • 61
  • 91
  • I know its a bad practice but I desperately need to do it this way as a temporary hack in our current project as a matter of urgency. We are going to fix it very soon. – user3219798 Feb 21 '14 at 04:43
0

Though the context of where you are going to use this unclear, I would just speculate that you are trying to get the rendered view so that it can be returned using Ajax and would simply allow you to update certain area of the page.

Well, This is not the correct way of MVC. As Rob said, you should try making use of JsonResult. If you think you want the returned data from Web Service to be passed in to the view then better try to get a JsonResult and call this method using Ajax.

Also, if you are trying somehow to replace the content of your page or element using this Rendered View as string, the better approach would be to simply create some partial views and call them in the View as @Html.Action("View","Controller"). This way you will even get the html. You can also call it using Ajax and push it to the container element where you want to display the view.

Anubhav Ranjan
  • 1,558
  • 3
  • 18
  • 32