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

I have an ASP.NET MVC 3 action method that accepts HttpFileCollectionBasean HTTP POST.

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

Currently, the action method is as follows:

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");   
}

This is basically a user profile page where they change their pic profile. Downloading takes place through jQuery AJAX.

Now, how can I turn off the three calls ResizeAndUploadas asynchronous tasks, but not return the result of the action until all three tasks are completed?

I used Task.Factory.StartNewto run asynchronous tasks, but that was when I did not care about waiting for the result.

Any ideas?

+3
6

, 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");   
}

, ResizeAndUpload - ( , ), , .

+7

Task.Factory.StartNew, @BFree answer:

public ActionResult ChangeProfilePicture()
{
   var fileUpload = Request.Files[0];
   var threads = new Task[3];
   threads[0] = Task.Factory.StartNew(()=>ResizeAndUpload(fileUpload.InputStream, Size.Original));
   threads[1] = Task.Factory.StartNew(()=>ResizeAndUpload(fileUpload.InputStream, Size.Profile));
   threads[2] = Task.Factory.StartNew(()=>ResizeAndUpload(fileUpload.InputStream, Size.Thumb));

   Task.WaitAll(threads, 120000); // wait for 2mins.

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

, Thread Task .

+6

, Task ManualResetEvent

public ActionResult Sample()
    {
        var wh1 = new ManualResetEvent(false);
        var wh2 = new ManualResetEvent(false);
        var wh3 = new ManualResetEvent(false);

        Task.Factory.StartNew(new Action<object>(wh =>
        {
            // DoSomething();
            var handle = (ManualResetEvent)wh;
            handle.Set();
        }), wh1);

        Task.Factory.StartNew(new Action<object>(wh =>
        {
            // DoSomething();
            var handle = (ManualResetEvent)wh;
            handle.Set();
        }), wh2);

        Task.Factory.StartNew(new Action<object>(wh =>
        {
            // DoSomething();
            var handle = (ManualResetEvent)wh;
            handle.Set();
        }), wh3);

        WaitHandle.WaitAll(new[] { wh1, wh2, wh3 });

        return View();
    }

, .

+1

, Task.WaitAll .

public MyViewModel LoadData()
{
    MyViewModel viewModel = null;

    try
    {
        Task.Factory.StartNew(() =>
           {
               var task1 = Task<MyViewModel>.Factory.StartNew(() =>
               {
                   return BuildMyViewModel(args);
               });

               var task2 = Task<ViewModel2>.Factory.StartNew(() =>
               {
                   return BuildViewModel2(args);
               });

               var task3 = Task<ViewModel3>.Factory.StartNew(() =>
               {
                   return BuildViewModel3(args);
               });

               Task.WaitAll(task1, task2, task3);

               viewModel = task1.Result;

               viewModel.ViewModel2 = task2.Result;
               viewModel.ViewModel3 = task3.Result;

           }).Wait();
    }
    catch (AggregateException ex)
    {
        System.Diagnostics.Trace.WriteLine(ex.StackTrace); 
        // ...
    }

    return viewModel;
}
+1

MVC, . :

http://msdn.microsoft.com/en-us/library/ee728598.aspx

you can still use Tasks, but don’t need any special processing that allows you to perform async actions

0
source

You can create a task with child tasks. The parent task will be completed when all child tasks are completed.

Example:

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

    Task.Factory.StartNew(() =>
    {
        Task.Factory.StartNew(() => 
            ResizeAndUpload(fileUpload.InputStream, Size.Original), 
            TaskCreationOptions.AttachedToParent);

        Task.Factory.StartNew(() => 
            ResizeAndUpload(fileUpload.InputStream, Size.Profile), 
            TaskCreationOptions.AttachedToParent);

        Task.Factory.StartNew(() => 
            ResizeAndUpload(fileUpload.InputStream, Size.Thumb), 
            TaskCreationOptions.AttachedToParent);
    }).Wait();

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

All Articles