res)
Console.WriteLine(line);
var res = lines.Where(x => x.StartsWith("ERROR: ")).Select(x => x.Substring("ERROR: ".Length));
如果使用了新的IAsyncEnumerable
,你会发现无法使用Where
等操作符了:
ErrorCS1936Could not find an implementation of the query pattern for source type 'IAsyncEnumerable<string>'. 'Where' not found.AsyncLinqDemoC:\Source\Workspaces\Console\AsyncLinqDemo\AsyncLinqDemo\Program.cs16Active
目前LINQ
还没有提供对IAsyncEnumerable
的原生支持,不过微软提供了一个Nuget包来实现此功能。在项目中打开Nuget Package Manger搜索安装System.Linq.Async
,注意该包目前还是预览版,所以要勾选include prerelease
才能看到。安装该Nuget包后,Linq查询语句中的错误就消失了。
在System.Linq.Async
这个包中,对每个同步的LINQ
方法都做了相应的扩展。所以基本上代码无需什么改动即可正常编译。
对于LINQ
中的条件语句,也可以使用WhereAwait()
方法来支持await
:
public static IAsyncEnumerable<TSource> WhereAwait<TSource>(thisIAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<bool>>predicate);
如需要在条件语句中进行IO或网络请求等异步操作,可以这样用:
var res = lines.WhereAwait(async x => await DoSomeHeavyOperationsAsync(x));
DoSomeHeavyOperationsAsync
方法的签名如下:
private static ValueTask<bool> DoSomeHeavyOperationsAsync(string x)
//Do some works...
通过以上的示例,我们简要了解了如何使用IAsyncEnumerable
接口以及如何在LINQ
中实现异步查询。在使用该接口时,我们需要创建一个自定义方法返回IAsyncEnumerable<T>
来代替IEnumberable<T>
,这个方法可称为async-iterator
方法,需要注意以下几点:
该方法应该被声明为async
。
返回IAsyncEnumerable<T>
。
同时使用await
及yield
。如await foreach
,yield return
或yield break
等。
async IAsyncEnumerable<int> GetValuesFromServer()
while (true)
IEnumerable<int> batch = await GetNextBatch();
if (batch == null) yield break;
foreach (int item in batch)
yield return item;
此外还有一些限制:
无法在try
的finally
块中使用任何形式的yield
语句。
无法在包含任何catch
语句的try
语句中使用yield return
语句。
期待.NET Core 3的正式发布!
了解新西兰IT行业真实码农生活
请长按上方二维码关注“程序员在新西兰”