3

我有一个接受HttpFileCollectionBaseHTTP POST 的 ASP.NET MVC 3 操作方法。

在这种方法中,我需要调整图像大小并上传 3 次。

action 方法目前看起来像这样:

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

基本上这是一个用户个人资料页面,他们在其中更改个人资料图片。上传通过 jQuery AJAX 进行。

现在,我怎样才能将三个调用作为异步任务触发ResizeAndUpload,但在所有三个任务都完成之前不返回操作结果?

以前我一直使用Task.Factory.StartNew触发异步任务,但那是我不在乎等待结果的时候。

有任何想法吗?

4

6 回答 6

7

一种简单的方法是使用 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 方法可能在某处阻塞(如果没有看到代码就无法确定),但在这种情况下,可能值得重构它们以使它们异步。

于 2011-06-01T00:21:45.143 回答
6

还可以使用Task.Factory.StartNew,类似于@BFree 的回答:

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

现在确定是否ThreadTask更好。

于 2011-06-01T00:32:21.783 回答
1

使用 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();
    }

希望这可以帮助。

于 2011-06-01T01:10:02.577 回答
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;
}
于 2012-02-15T00:30:17.777 回答
0

MVC 操作还有一个异步模式,请参阅此链接:

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

您仍然可以使用任务,但不需要任何特殊处理来允许操作异步执行

于 2011-06-01T00:39:43.577 回答
0

你可以用子任务组成一个任务。当所有子任务都完成后,父任务将完成。

例子:

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");
}
于 2013-06-19T15:01:27.493 回答