MVC5网站中的批处理
Batch processing in MVC5 website
我有一个使用 EF 进行数据访问的 MVC 网站。该应用程序接收数据,运行s 一系列计算并存储结果。每批数据可以有几千条记录,计算平均需要 30 秒 - 我想 运行 所有这些都在后台。
到目前为止,我已经准备好 Hangfire 来触发批处理。然后我做:
var queue = new Queue<MyItem>();
// queue is populated ...
while (queue.Any())
{
var item = queue.Dequeue();
var task = Task.Run(() =>
{
using (var context = new MyDbContext())
{
context.MyItem.Add(item);
// Run Calculations
try {
context.SaveChanges();
}
catch {
// Log error
}
}
}
}
当批处理 运行 站点变得完全没有响应时,或者我收到 'The underlying provider failed on Open' 错误。
有更好的方法吗?
您似乎正在使用 Task.Run
创建任务,而不是等待它们完成。这意味着您将为队列中的每个项目生成一个任务,该任务将 运行 在不同的 ThreadPool
线程上同时进行。这可能是一个很大的负担,可能(并且可能确实)影响您的常规请求。
您应该以某种方式限制这些任务的并发。最简单的 IMO 是使用 TPL Dataflow 的 ActionBlock
。您使用委托和选项(例如 MaxDegreeOfParallelism
)创建块,将 post 项放入其中并等待它完成:
block = new ActionBlock<MyItem>(item =>
{
using (var context = new MyDbContext())
{
context.MyItem.Add(item);
// Run Calculations
try {
context.SaveChanges();
}
catch {
// Log error
}
}
}, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2 });
while (queue.Any())
{
var item = queue.Dequeue();
block.Post(item);
}
block.Complete();
await block.Completion;
我有一个使用 EF 进行数据访问的 MVC 网站。该应用程序接收数据,运行s 一系列计算并存储结果。每批数据可以有几千条记录,计算平均需要 30 秒 - 我想 运行 所有这些都在后台。
到目前为止,我已经准备好 Hangfire 来触发批处理。然后我做:
var queue = new Queue<MyItem>();
// queue is populated ...
while (queue.Any())
{
var item = queue.Dequeue();
var task = Task.Run(() =>
{
using (var context = new MyDbContext())
{
context.MyItem.Add(item);
// Run Calculations
try {
context.SaveChanges();
}
catch {
// Log error
}
}
}
}
当批处理 运行 站点变得完全没有响应时,或者我收到 'The underlying provider failed on Open' 错误。
有更好的方法吗?
您似乎正在使用 Task.Run
创建任务,而不是等待它们完成。这意味着您将为队列中的每个项目生成一个任务,该任务将 运行 在不同的 ThreadPool
线程上同时进行。这可能是一个很大的负担,可能(并且可能确实)影响您的常规请求。
您应该以某种方式限制这些任务的并发。最简单的 IMO 是使用 TPL Dataflow 的 ActionBlock
。您使用委托和选项(例如 MaxDegreeOfParallelism
)创建块,将 post 项放入其中并等待它完成:
block = new ActionBlock<MyItem>(item =>
{
using (var context = new MyDbContext())
{
context.MyItem.Add(item);
// Run Calculations
try {
context.SaveChanges();
}
catch {
// Log error
}
}
}, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2 });
while (queue.Any())
{
var item = queue.Dequeue();
block.Post(item);
}
block.Complete();
await block.Completion;