当前位置: 首页 > 知识库问答 >
问题:

linq选择中的异步等待

曹浩波
2023-03-14

我需要修改一个现有的程序,它包含以下代码:

var inputs = events.Select(async ev => await ProcessEventAsync(ev))
                   .Select(t => t.Result)
                   .Where(i => i != null)
                   .ToList();

但这在我看来非常奇怪,首先是在select中使用AsyncAwait。根据斯蒂芬·克利里的回答,我应该能够放弃这些。

然后第二个select,它选择结果。这是不是意味着任务根本不是异步的,而是同步执行的(这么多的努力是徒劳无功的),或者任务是异步执行的,当它完成后,查询的其余部分将被执行?

我是否应该按照Stephen Cleary的另一个答案,像下面这样编写上述代码:

var tasks = await Task.WhenAll(events.Select(ev => ProcessEventAsync(ev)));
var inputs = tasks.Where(result => result != null).ToList();

而且像这样完全一样吗?

var inputs = (await Task.WhenAll(events.Select(ev => ProcessEventAsync(ev))))
                                       .Where(result => result != null).ToList();

当我在这个项目中工作时,我想更改第一个代码示例,但我不太热衷于更改(明显工作的)异步代码。也许我只是在担心什么,所有的3个代码样本都做了完全一样的事情?

ProcessEventsAsync如下所示:

async Task<InputResult> ProcessEventAsync(InputEvent ev) {...}

共有1个答案

石喜
2023-03-14
var inputs = events.Select(async ev => await ProcessEventAsync(ev))
                   .Select(t => t.Result)
                   .Where(i => i != null)
                   .ToList();

但这对我来说似乎很奇怪,首先是使用异步和等待中的选择。根据斯蒂芬·克利里的回答,我应该能够放弃这些。

select的调用有效。这两行基本上是相同的:

events.Select(async ev => await ProcessEventAsync(ev))
events.Select(ev => ProcessEventAsync(ev))

(关于如何从processEventAsync引发同步异常有一点小差异,但在此代码的上下文中,这一点都不重要。)

然后是选择结果的第二个Select。这是不是意味着任务根本不是异步的,而是同步执行的(这么多的努力是徒劳无功的),或者任务是异步执行的,当它完成后,查询的其余部分将被执行?

表示查询正在阻塞。所以它并不是真正的异步。

分解它:

var inputs = events.Select(async ev => await ProcessEventAsync(ev))

将首先为每个事件启动异步操作。然后这行:

                   .Select(t => t.Result)

将等待这些操作一次完成一个(首先它等待第一个事件的操作,然后是下一个,然后是下一个,等等)。

这是我不关心的部分,因为它阻止并将任何异常包装在AggregateException中。

var tasks = await Task.WhenAll(events.Select(ev => ProcessEventAsync(ev)));
var inputs = tasks.Where(result => result != null).ToList();

var inputs = (await Task.WhenAll(events.Select(ev => ProcessEventAsync(ev))))
                                       .Where(result => result != null).ToList();

是的,那两个例子是等价的。它们都启动所有异步操作(events.select(...)),然后异步等待所有操作以任何顺序完成(await task.whenall(...)),然后继续其余的工作(where...)。

这两个示例都不同于原始代码。原始代码正在阻塞,并将异常包装在AggregateException中。

 类似资料:
  • 问题内容: 我的SQL代码如下: 等效的linq表达式是什么? 问题答案: 我第一次尝试在 来源 LINQ to SQL中的NOT IN子句

  • 问题内容: 我有一个结果的,我只需要选择从。 我的查询是这样的: 那可能吗?任何帮助将不胜感激。 实际上,我将其作为a绑定到控件,并且该控件同时显示这两个控件。但是我只想显示。 当我尝试使用时,出现类似以下错误: LINQ to Entities不支持指定的类型成员’Date’。仅支持初始化程序,实体成员和实体导航属性。 问题答案: 如果出于演示目的,则可以使用属性。例如,如果要将数据源绑定到Gr

  • 我试图在react/electron项目中使用async/await,但它不起作用。我想要的是获取docker容器状态列表。但是安慰。日志(列表)返回未定义的。 有人能帮我吗?:)

  • 问题内容: 在Swift语言中是否存在LINQ Select()方法的替代方法? 例如,在c#中,我可以执行以下操作: 但是我怎么能用Swift语言做同样的事情呢? 问题答案: 这是语法糖: 应用的语法糖包括: 尾随闭包语法 } 参数类型推断 } 返回类型推断 } 隐式返回值 card.rank } 匿名闭包参数 请查看有关闭包的语言指南部分(C#称为 lambdas 的Swift名称)以获取更多

  • 但是,了解node.js事件循环会发现: 当然,在后端,有用于DB访问和进程执行的线程和进程。 在C#中,编写带有标记的函数和带有的调用就足够了,这样.NET就可以将它放在另一个线程中。但是,node.js中组织方式不同的东西让我很困惑,async/await函数仍然会阻塞主线程。

  • 问题内容: 我正在使用Entity Framework Code First开发WCF RESTful Web服务。 我的桌子上有很多列。我这样做是为了获得特定用户: 在此表上,有一个密码列,我不想返回此列。 如何从该选择中排除密码列? 问题答案: 在select语句中指定所需的每一列: