yaz*_*pro 12 c# asp.net asynchronous hangfire
我正在从Task.Run切换到Hangfire.在.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";
}
Run Code Online (Sandbox Code Playgroud)
据我所知,从Hangfire 的快速入门页面,您的主要人员BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget"));
完全将代码作为后台作业运行,但显然不支持具有返回值的作业(如上面提到的代码).是对的吗?如果没有,我如何调整我的代码才能使用Hangfire?
PS我已经看过HostingEnvironment.QueueBackgroundWorkItem(这里),但它显然缺乏相同的功能(后台工作必须void)
编辑
正如@Dejan所知,我想切换到Hangfire的主要原因与.NET人员QueueBackgroundWorkItem在.NET 4.5.2中添加的原因相同.这个原因在Scott Hanselman 关于ASP.NET背景任务的伟大文章中得到了很好的描述.所以我要引用这篇文章:
QBWI(QueueBackgroundWorkItem)调度可以在后台运行的任务,与任何请求无关.这与普通的ThreadPool工作项不同,因为ASP.NET自动跟踪通过此API注册的工作项当前正在运行,并且ASP.NET运行时将尝试延迟AppDomain关闭,直到这些工作项完成执行.
Dej*_*jan 11
一个简单的解决方案是轮询监控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;
}
Run Code Online (Sandbox Code Playgroud)
注意:当然,在Web托管的场景中,您不能依赖于task(task.ContinueWith())的继续来在作业完成后执行更多操作,因为AppDomain可能会被关闭 - 出于同样的原因,您可能希望在第一名.