我正试图准确地了解由QueueBackgroundWorkerItem线程启动的任务的状态。我可以访问任务对象并将其添加到我的TaskModels列表中,然后将该列表对象发送到我的视图中。
无论我单击QueueWorkItem链接多少次并启动新任务,我的视图都只显示一个任务状态。我想弄清楚两件事:
-
在MVC中,我如何保存生成的任务数量的实时列表?我认为,通过将模型发送到视图,我可以确保某种永久性。
-
一旦我能做到这一点,我假设我能够将任务对象存储在我的列表中。然而,即使在下面的示例中,我似乎仍然无法知道任务在任何给定时间的状态(似乎只有在将其添加到列表时才能知道它是什么)。
我希望有人做过类似的事情,并能对此有所帮助。
谢谢
-杰森
编辑:此设置的核心要求是:
-
即使浏览器关闭,我也需要使用QueueBackgroundWorkerItem来运行长作业
-
我选择嵌入任务,以便了解每个作业运行的持续状态。我理解,使用QBWI,运行任务将是过分的。但我找不到其他方法来了解QBWI在任何时候的状态。
控制器:
List<TaskModel> taskModelList = new List<TaskModel>();
public ActionResult QueueWorkItem()
{
Task task;
ViewBag.Message = "State: ";
String printPath = @"C:\Work\QueueBackgroundWorkerItemPractice\QueueBackgroundWorkerItemPractice\WorkerPrintFile" + DateTime.Now.ToLongTimeString().ToString().Replace(":", "_") + ".txt";
System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
task = Task.Run(() =>
{
string filePath = printPath;
string text = "File line ";
if (!System.IO.File.Exists(filePath))
{
using (var stream = System.IO.File.Create(filePath)) { }
}
TextWriter tw = new StreamWriter(printPath);
for (int i = 0; i < 400; i++)
{
text = "Line " + i;
tw.WriteLine(text);
Thread.Sleep(200);
}
tw.Close();
});
var c = task.ContinueWith((antecedent) =>
{
taskModelList.Add(new TaskModel(task));
});
});
return View(taskModelList);
}
查看:
@model List<QueueBackgroundWorkerItemPractice.Models.TaskModel>
@{
ViewBag.Title = "Queue Background Worker";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message<span id="modelClass"></span></h3>
<p>Use this area to provide additional information.</p>
@{
<ul>
@foreach (var taskModel in Model)
{
<li>@taskModel.Status</li>
}
</ul>
}
编辑,解决方案:
根据拉斐的建议和以下妥协,我能够找到这样的建议:
-
我们在任何给定时间只运行一个任务。我不需要清单
-
我真的不需要状态随需应变。我只想知道什么时候完工
我希望能够利用任务ID稍后从ID实例化任务。事实证明,这涉及的开销比必要的多。
相反,我找到了功能
Task.CompletedTask
(在.NET 4.6及更高版本中提供)。这在异步中使用,允许我在任务完成时获取任务的状态。瞧。谢谢大家的建议。
最好的部分-无论我是否关闭浏览器,这个长期运行的任务都将完成。。。或
停止IIS
。神奇的
public ActionResult QueueWorkItem()
{
System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
{
task = Task.Run(async () =>
{
String printPath = @"C:...";
string filePath = printPath;
string text = "File line ";
if (!System.IO.File.Exists(filePath))
{
using (var stream = System.IO.File.Create(filePath)) { }
}
TextWriter tw = new StreamWriter(printPath);
for (int i = 0; i < 400; i++)
{
text = "Line " + i;
tw.WriteLine(text);
Thread.Sleep(200);
}
tw.Close();
await Task.CompletedTask;
});
var c = task.ContinueWith((antecedent) =>
{
taskID = task.Id;
status = task.Status.ToString();
try
{
string connString = WebConfigurationManager.ConnectionStrings["TaskContext"].ToString();
sqlCommand.CommandText = "INSERT INTO dbo.TaskTable (TaskId, Status) VALUES (" + taskID + ", '" + status + "')";
conn.ConnectionString = connString;
sqlCommand.Connection = conn;
conn.Open();
sqlCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
String info = ex.Message + ex.ToString() + ex.StackTrace;
throw new Exception("SQL Issue" + info);
}
finally
{
if (conn != null)
{
conn.Close();
conn = null;
}
sqlCommand = null;
}
});
});
return View();
}