我要从Task.Run https://msdn.microsoft.com/en-us/library/hh195051%28v=vs.110%29.aspx to Hangfire http://docs.hangfire.io/en/latest/quick-start.html。在 .NET 4.5+ 中Task.Run
可以返回Task<TResult>
这允许我运行返回的任务void
。我通常可以通过访问该属性来等待并获取任务结果MyReturnedTask.Result
我的旧代码示例:
public void MyMainCode()
{
List<string> listStr = new List<string>();
listStr.Add("Bob");
listStr.Add("Kate");
listStr.Add("Yaz");
List<Task<string>> listTasks = new List<Task<string>>();
foreach(string str in listStr)
{
Task<string> returnedTask = Task.Run(() => GetMyString(str));
listTasks.Add(returnedTask);
}
foreach(Task<string> task in listTasks)
{
// using task.Result will cause the code to wait for the task if not yet finished.
// Alternatively, you can use Task.WaitAll(listTasks.ToArray()) to wait for all tasks in the list to finish.
MyTextBox.Text += task.Result + Environment.NewLine;
}
}
private string GetMyString(string str)
{
// long execution in order to calculate the returned string
return str + "_finished";
}
据我所知快速开始 http://docs.hangfire.io/en/latest/quick-start.htmlHangfire 的页面,你的主要人物是BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget"));
完美地将代码作为后台作业运行,但显然不支持具有返回值的作业(如我上面提供的代码)。是对的吗?如果没有,我该如何调整我的代码才能使用 Hangfire?
附:我已经看过了HostingEnvironment.QueueBackgroundWorkItem
(here http://blogs.msdn.com/b/webdev/archive/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-long-background-process-in-asp-net.aspx)但它显然缺乏相同的功能(后台作业必须是void
)
EDIT
正如@Dejan 所指出的,我想切换到 Hangfire 的主要原因与 .NET 人员添加的原因相同QueueBackgroundWorkItem
在 .NET 4.5.2 中。斯科特·汉塞尔曼 (Scott Hanselman) 的伟大著作中很好地描述了这个原因article http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx关于 ASP.NET 中的后台任务。所以我要引用这篇文章:
QBWI(QueueBackgroundWorkItem)调度一个可以在后台运行的任务,独立于
任何请求。这与普通 ThreadPool 工作项的不同之处在于
ASP.NET 自动跟踪注册的工作项数量
通过此 API 当前正在运行,并且 ASP.NET 运行时将
尝试延迟 AppDomain 关闭,直到这些工作项完成
执行。
一种简单的解决方案是轮询监控 API,直到作业完成,如下所示:
public static Task Enqueue(Expression<Action> methodCall)
{
string jobId = BackgroundJob.Enqueue(methodCall);
Task checkJobState = Task.Factory.StartNew(() =>
{
while (true)
{
IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi();
JobDetailsDto jobDetails = monitoringApi.JobDetails(jobId);
string currentState = jobDetails.History[0].StateName;
if (currentState != "Enqueued" && currentState != "Processing")
{
break;
}
Thread.Sleep(100); // adjust to a coarse enough value for your scenario
}
});
return checkJobState;
}
注意力:当然,在 Web 托管的场景中,您不能依赖任务的继续(task.ContinueWith()
)在作业完成后执行更多操作,因为 AppDomain 可能会关闭 - 出于同样的原因,您可能首先想要使用 Hangfire。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)