【问题标题】:EF Async Methods - best practices / improvementsEF 异步方法 - 最佳实践/改进
【发布时间】:2016-05-05 14:52:27
【问题描述】:

很抱歉这样的主观问题:

我目前有一个非常慢的顺序加载方法,我已将其转换为异步方法:

    public async void LoadData(int releaseId, int projectId, bool uiThread)

在这个方法中,我启动了一个等待任务(并将 ConfigureAwait 设置为 false),因为它不需要从这个上下文中捕获和恢复。

     await Task.Run(() =>
     { 
         //make several DB calls as below 

     }).ConfigureAwait(False);

在这个任务中,我对 EF / 数据库进行了几次异步调用,每个调用看起来像这样:

    public async virtual Task<List<X>> FindXAsync()
    {
        var q = from c in context.X
                select c;
        return await q.ToListAsync();
    }

但在任务中,我正在等待使用结果的响应,如下所示:

    X = sm.FindXAsync().Result;

根据我对 EF 使用异步编程的有限知识,每个调用是否会从任务内部按顺序运行?

当前设置会同时返回多个返回集,还是我必须创建多个任务并分别等待它们。

再次抱歉这个模糊的问题,但我相信你们在这个话题上比我更有经验^^


编辑:我发布了那里没有真正合适的问题,我想我想知道的是 x、y 和 z 会在任务中同时或按顺序返回。

     await Task.Run(() =>
     {
          x = sm.FindXAsync().Result;

          y = new ObservableCollection<Y>(sm.FindYAsync().Result);

          z = new ObservableCollection<Z>(sm.FindZAsync().Result);
     }).ConfigureAwait(False)

谢谢,

克里斯

【问题讨论】:

  • "每个调用会从任务内部按顺序运行吗?"在任务内部(如果您不故意同步运行),是的,如果您等待它们。您不需要使用Task.Run 在不同的线程上运行它们,asyc 方法本身就足够了。
  • @Transcendent 所以任务中的异步方法将在自己的线程上运行,尽管需要任务中的结果?
  • 实际上您在代码中编写的任务不接受任何异步功能。所以代码本身就有问题。但是为什么要使用Task,请详细说明。
  • 主要是为了速度优势,理想情况下将部分负载转移到他们自己的长时间运行的任务/线程上。我首先添加了一个任务来包含几个异步 DB 调用,但我想这并没有达到我的预期

标签: c# entity-framework asynchronous task


【解决方案1】:

是的,当您使用 Result 属性时将按顺序运行。它们还将使用以下代码按顺序运行:`

    x = await sm.FindXAsync().ConfigureAwait(False);

    y = new ObservableCollection<Y>( await sm.FindYAsync().ConfigureAwait(False));

    z = new ObservableCollection<Z>(await sm.FindZAsync().ConfigureAwait(False));

也更新

 public async void LoadData to return Task ->  `public async Task LoadData`.

如果您想并行运行所有代码,请将任务添加到数组中,然后调用await Task.WhenAll(tasks)

【讨论】:

  • 所以我必须创建每个任务作为异步管理器方法的返回,然后使用 Task.WhenAll(tasks) 然后将结果分配给局部变量? - 谢谢克里斯
  • @Chris,不,只使用这个: var tasks = new Task[] {sm.FindXAsync(), sm.FindYAsync(), sm.FindZAsync()};等待 Task.WhenAll(tasks); x = 任务[0].结果; y = new ObservableCollection(tasks[1].Result); z = new ObservableCollection(tasks[2].Result)
  • 好的,谢谢,我假设 FindXAsync 方法返回时的等待不会影响其他两个任务(查找 y 和查找 z)的运行 - 标记为答案,感谢您的帮助 :)
  • 关于更改加载数据以返回 Task 而不是 void,这是否意味着必须等待调用 - 并且要使用等待调用,包装方法需要是异步的等等..有什么办法可以避免这种情况?
  • 在实施解决方案建议解决方案后确定,我收到以下错误“在前一个异步操作完成之前,在此上下文上启动了第二个操作。使用‘await’确保之前完成的任何异步操作在此上下文中调用另一个方法。不保证任何实例成员都是线程安全的” - 我认为这是由于管理器方法的重叠上下文,但为每个成员添加等待基本上会使它们按顺序运行,对吗?这是我不想要的。
猜你喜欢
  • 2010-10-09
  • 1970-01-01
  • 2011-08-12
  • 2013-02-02
  • 1970-01-01
  • 2018-12-26
  • 2018-11-24
  • 2020-08-26
  • 1970-01-01
相关资源
最近更新 更多