我在枚举IAsyncEnumerable
, 并附加了System.Linq.Async运算符时遇到了一个奇怪的问题。Take
在我的迭代器中,我有一个 try-finally 块,块内产生了一些值,try
块内有一些清理代码finally
。清理代码位于lock
块内。问题是块后面的任何代码lock
都不会执行。没有抛出异常,只是忽略了代码,就像它不存在一样。这是一个重现此行为的程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class Program
{
static async Task Main()
{
await foreach (var item in GetStream().Take(1))
{
Console.WriteLine($"Received: {item}");
}
Console.WriteLine($"Done");
}
static async IAsyncEnumerable<int> GetStream()
{
var locker = new object();
await Task.Delay(100);
try
{
yield return 1;
yield return 2;
}
finally
{
Console.WriteLine($"Finally before lock");
lock (locker) { /* Clean up */ }
Console.WriteLine($"Finally after lock");
}
}
}
输出:
Received: 1
Finally before lock
Done
控制台中未打印文本“Finally after lock” !
这只发生在Take
连接了操作员的情况下。如果没有操作符,文本将按预期打印。
这是System.Linq.Async
库中的错误、C# 编译器中的错误还是其他什么?
作为一种解决方法,我目前在 内部使用嵌套的 try-finally 块finally
,它可以工作但很尴尬:
finally
{
try
{
lock (locker) { /* Clean up */ }
}
finally
{
Console.WriteLine($"Finally after lock");
}
}
.NET Core 3.1.3、.NET Framework 4.8.4150.0、C# 8、System.Linq.Async 4.1.1、Visual Studio 16.5.4、控制台应用程序