【问题标题】:Async/Await with Tasks.WhenAll in For Loop Not Running In ParallelAsync/Await with Tasks.WhenAll in For 循环未并行运行
【发布时间】:2020-05-23 00:46:58
【问题描述】:

我正在进行数据迁移,其中有一长串宠物,我正在循环执行迁移。为了迁移每个宠物,必须完成大量业务逻辑。我希望一次运行多个迁移任务以加快速度,但是下面的异步添加似乎与同步运行相同。我发现了几个关于此的堆栈溢出响应和博客文章,但由于某种原因,这仍然无法正常工作。

我试图将下面的代码保持在所需的最低限度,但如果需要更多上下文,我可以提供。

public static async Task MigrationAsync(MyDbContext myContext)
{
    await MainMigrationAsync(myContext);

}

public static async Task MainMigrationAsync(MyDbContext myContext)
{
    var pets = myContext.Pets.ToList();

    var tasks = new List<Task>();
    for (var eachPet = 0; eachRelation < pets.Count; eachRelation++)
    {
        var task = SingleLongRunningPetMigrationAsync(myContext, pets[eachPet]);
        tasks.Add(task);
    }
    await Task.WhenAll();

    myContext.SaveChanges();
}

public static async Task SingleLongRunningPetMigrationAsync(MyDbContext myContext, Pet pet)
{
    //these need to run synchronously for each pet, but need multiple pet tasks to be running at once
    MigrationMethodOne(myContext);
    MigrationMethodTwo(myContext);
    MigrationMethodThree(myContext);
    MigrationMethodFour(myContext);
}

【问题讨论】:

  • 您似乎以多线程方式使用单个 EF 上下文。这是不允许的,应该抛出异常。
  • SingleLongRunningPetMigrationAsync 中是否有任何类型的锁定?
  • 暂时没有锁定。关于 dbcontext 的要点。也需要在这里研究策略。
  • 你是从主线程运行这段代码吗?如果是这样,除了数据库访问层可能在内部之外,不会有任何线程进行。
  • 请注意SingleLongRunningPetMigrationAsync 中的所有内容都将同步运行到第一个await

标签: c# asynchronous async-await


【解决方案1】:

重要提示:由于 EF 内核不允许并行使用 DbContext,因此您必须为每个“作业”提供一个 DbContext

并且SingleLongRunningPetMigrationAsync方法中没有await,所以它不应该是async Task类型,只有void

例如,您可以在场景中使用“Parallel.ForEach”(假设每个调用都有自己的DbContext)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 2019-11-06
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    相关资源
    最近更新 更多