Search code examples
c#asp.net-mvc-3file-uploadtask-parallel-libraryasynchronous-method-call

ReadOnly Session coupled with Asynchronous Action and Task Thread. How does the Controller behave then?


In an Asp.Net MVC application if an Asynchronous Controller's Session behavior is Read only, its Action method is also Asynchronous and within it we create a Task Thread that does some long running stuff, example:

[SessionState(SessionStateBehavior.ReadOnly)]
public class UploadController : AsyncController
{
    public void UploadFilesAsync(IEnumerable<HttpPostedFileBase> assetFiles, 
                             string filesMetaInfo)
   {
       var postedFiles = assetFiles;
       var fInfo = filesMetaInfo;

       AsyncManager.OutstandingOperations.Increment();

      Task.Factory.StartNew(
        () => ProcessUploadedFile(postedFiles, fInfo),
        CancellationToken.None, TaskCreationOptions.DenyChildAttach, 
        TaskScheduler.FromCurrentSynchronizationContext());
   }

   public ActionResult UploadFilesCompleted(object result)
   {
      return Json(new
      {
         status = "OK"
      }, "text/plain");
   }

   private void ProcessUploadedFile(IEnumerable<HttpPostedFileBase> 
                     assetFiles, string filesInfo)
   {
          // Do some long running stuff here like file processing.
          // ......................
          // ..................................

          AsyncManager.Parameters["result"] = "success"
          AsyncManager.OutstandingOperations.Decrement();
    }
}

Two questions now:

  1. Will this Controller Action method UploadFilesAsync(), release this Controller for other Requests once the inside Task thread work completes fully or be available to other Requests right after when the Task just starts executing?

  2. Also what will happen if I make this UploadFilesAsync() method behave in a synchronous manner by applying "Synchronized" attribute on it? example:

    [MethodImpl(MethodImplOptions.Synchronized)]


Solution

  • Will this Controller Action method UploadFilesAsync(), release this Controller for other Requests once the inside Task thread work completes fully or be available to other Requests right after when the Task just starts executing?

    By "release this controller" I'm assuming you mean release the ASP.NET threadpool thread currently occupied with processing your message. If so, the answer is the latter. It will release the current thread immediately without waiting for the inner task executed to complete.

    Also what will happen if I make this UploadFilesAsync() method behave in a synchronous manner by applying "Synchronized" attribute on it?

    MethodImplOptions.Synchronized does not make the method run synchronously. It merely is like wrapping your whole method executing with lock (this). This would mean the that multiple callers won't be able to use the same instance of your Controller, but that doesn't happen anyway, as a new Controller is spun up for every request made. That means it will make no difference whatsoever.

    As a side note - You should not be using Task.Factory.StartNew nor Task.Run inside ASP.NET, because any work offloaded to that threadpool thread will not be registered with IIS, which means your thread could be abnormally aborted due to IIS recycling. Instead, look into HostingEnvironment.QueueBackgroundWorkItem if you're using .NET 4.5.2, or look into Stephan Clearys AspNetBackgroundTasks