【问题标题】:is a background worker in a controller async?控制器中的后台工作人员是异步的吗?
【发布时间】:2010-08-24 22:47:12
【问题描述】:
在 asp.net mvc 2 控制器中,我有以下代码:
using (BackgroundWorker worker = new BackgroundWorker())
{
worker.DoWork += new DoWorkEventHandler(blah);
worker.RunWorkerAsync(var);
}
我的问题是:这段代码是异步的吗,这意味着它会启动一个新线程,并且控制器会在“blah”并行执行时返回视图?
如果不是,我将如何实现这些结果?
【问题讨论】:
标签:
c#
asp.net-mvc
asp.net-mvc-2
【解决方案1】:
在 MVC 2 中有一个称为 AsyncController 的新功能,它是在 MVC 中进行异步调用的正确方法。你的控制器应该继承自 AsyncController 而不是控制器。然后,您的主要操作方法名称应以“Async”结尾。例如,如果您有一个名为 Blah() 的操作方法,则改为在 BlahAsync() 中命名,这将被框架自动识别(并使用 BlahCompleted() 进行回调):
public virtual void BlahAsync()
{
AsyncManager.OutstandingOperations.Increment();
var service = new SomeWebService();
service.GetBlahCompleted += (sender, e) =>
{
AsyncManager.Parameters["blahs"] = e.Result;
AsyncManager.OutstandingOperations.Decrement();
};
service.GetBlahAsync();
}
public virtual ActionResult BlahCompleted(Blah[] blahs)
{
this.ViewData.Model = blahs;
return this.View();
}
在此处了解有关 AsyncController 的更多信息:MVC AsyncController
【解决方案2】:
BackgroundWorker 并不是您真正想要的:没有可通过回调更新的 UI。您只想将工作项触发到线程池线程并继续前进。
ThreadPool.QueueUserWorkItem 方法可能更适合这里,或者使用新的任务并行方法:Task.Factory.StartNew(...)。
【解决方案3】:
我不确定这是否适合你(我不是说它不会,只是我不确定确定)。
简短的回答是是,代码是异步的。但是为了从BackgroundWorker 获得任何类型的返回值,您需要处理它的RunWorkerCompleted 事件。
基本机制是在DoWork 事件中的e.Result 属性中添加一些值,然后从RunWorkerCompleted 事件中的e.Result 属性中检索它(确保首先检查e.Error查看DoWork中是否抛出异常。
我不确定它是否会成功的原因是您使用了using 关键字,它确保BackgroundWorker 在代码块的末尾被丢弃。由于它异步执行其工作,这可能会或可能不会阻止您有机会处理RunWorkerCompleted。我真的不确定——也许其他人知道?
【解决方案4】:
我认为您可能会遇到问题,因为它会在后台线程仍在使用时尝试处置工作人员。如果没有别的,就是不可预测的行为。