正确使用异步/等待多个任务到Db

Ibr*_*taz 3 .net c# task-parallel-library async-await .net-4.5

我有一个简单的场景,但我想知道我的方法是否正确,是否更好地建议选择单个任务来保存我的失败订单,或者我可以启动并启动多个任务并等待它们全部完成.在连接到Db和保存实体时,此方案的正确方法是什么.

我已经有一个基于任务的单一版本,可以将一个实体保存到数据库中.

    public async static Task SaveOrdersAsync(OrderService oService, OrderItemService oiService, IEnumerable<OrderTemplate> toSaveList, IUnitOfWork uow, IProgress<string> progress)
    {
        var toSave = toSaveList as IList<OrderTemplate> ?? toSaveList.ToList();
        var tasks = new Task[toSave.Count()];

        for (var i = 0; i < tasks.Length; i++)
        {
            var i1 = i;

            tasks[i] = new Task(() => SaveToDb(oService, oiService, toSave.ElementAt(i1), uow), TaskCreationOptions.PreferFairness);

            var message = string.Format("- Order: {0} has been resaved.\n", toSave.ElementAt(i1).Order.FriendlyId);

            if (progress != null)
                progress.Report(message);
        }

        await Task.WhenAll(tasks);
    }
Run Code Online (Sandbox Code Playgroud)

目前,我已对上述内容进行了测试,并认为任务尚未开始,因为进度条不断循环.我的假设是Task.WhenAll应该为我开始我的任务 - 这就是我的想法?

或者应该在循环中使用它:

      tasks[i] = Task.Run(() => SaveToDb(oService, oiService, toSave.ElementAt(i1), uow));
Run Code Online (Sandbox Code Playgroud)

我想我很亲近,只是想让别人告诉我,我是否正确地做了这件事.

反馈合并版本:

    public async static Task SaveOrdersAsync(OrderService oService, OrderItemService oiService, IEnumerable<OrderTemplate> toSaveList, IUnitOfWork uow, IProgress<string> progress)
    {   
        var saveList = toSaveList as IList<OrderTemplate> ?? toSaveList.ToList();
        var saveTask = Task.Run(() =>
        {
            foreach (var ot in saveList)
            {
                SaveToDbBatch(oService, oiService, ot);

                var message = string.Format("- Order: {0} has been resaved.\n", ot.Order.FriendlyId);
                if (progress != null)
                    progress.Report(message);
            }
        });

        await saveTask;
        await Cache.UoW.SaveAsync();
    }
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 6

在连接到Db和保存实体时,此方案的正确方法是什么.

一般来说,你应该:

  1. 如果可能,批量保存.换句话说,调用单个方法同时更新多个记录.例如,EF有SaveChangesAsync.
  2. 使用数据库的自然异步API而不是Task.Run(或者更糟糕的是 - 任务构造函数).例如,EF有SaveChangesAsync.