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;