Search code examples
c#asp.net-mvcasp.net-mvc-3asynchronousasynccallback

How to fire an asynchronous task, but wait for all callbacks before returning ActionResult?


I have an ASP.NET MVC 3 action method which accepts a HttpFileCollectionBase in the HTTP POST.

In this method, i need to resize and upload the image 3 times.

The action method currently looks like this:

public ActionResult ChangeProfilePicture()
{
   var fileUpload = Request.Files[0];

   ResizeAndUpload(fileUpload.InputStream, Size.Original);
   ResizeAndUpload(fileUpload.InputStream, Size.Profile);
   ResizeAndUpload(fileUpload.InputStream, Size.Thumb);

   return Content("Success", "text/plain");   
}

Basically this is a user profile page, where they change their profile pic. The upload happens via jQuery AJAX.

Now, how can i fire off the three ResizeAndUpload calls as asynchronous tasks, but not return the action result until all three tasks have completed?

Previously i've been using Task.Factory.StartNew to fire off asynchronous tasks, but that was when i didn't care about waiting for the result.

Any ideas?


Solution

  • One simple way of doing it, is using Join:

    public ActionResult ChangeProfilePicture()
    {
       var fileUpload = Request.Files[0];
       var threads = new Thread[3];
       threads[0] = new Thread(()=>ResizeAndUpload(fileUpload.InputStream, Size.Original));
       threads[1] = new Thread(()=>ResizeAndUpload(fileUpload.InputStream, Size.Profile));
       threads[2] = new Thread(()=>ResizeAndUpload(fileUpload.InputStream, Size.Thumb));
    
       threads[0].Start();
       threads[1].Start();
       threads[2].Start();
    
       threads[0].Join();
       threads[1].Join();
       threads[2].Join();
    
       return Content("Success", "text/plain");   
    }
    

    It's possible though that the ResizeAndUpload method may be blocking somewhere (can't tell for sure without seeing the code) in which case it may be worthwhile to refactor those as well to make them async.