我有一个ASP.NET MVC 3操作方法,它接受HTTP POST中的HttpFileCollectionBase
。
在这种方法中,我需要调整大小并上传图像3次。
动作方法目前如下所示:
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
来启动异步任务,但那时我并不关心等待结果。
有什么想法吗?
答案 0 :(得分: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方法可能会在某处阻塞(无法在不看代码的情况下无法确定),但在这种情况下,重构这些也可能是值得的,以使它们异步。
答案 1 :(得分:6)
还使用Task.Factory.StartNew
使其工作,类似于@BBree的回答:
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
是否更好。
答案 2 :(得分: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();
}
希望这会有所帮助。
答案 3 :(得分: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;
}
答案 4 :(得分:0)
MVC操作还有一个异步模式,请参阅以下链接:
http://msdn.microsoft.com/en-us/library/ee728598.aspx
您仍然可以使用“任务”,但不需要任何特殊处理来允许操作执行异步
答案 5 :(得分: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");
}