-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Closed
Description
From this stackoverflow question.
Repro:
TargetFramework: netcoreapp3.1
.NET Core SDK (reflecting any global.json):
Version: 3.1.201
Commit: b1768b4ae7
Runtime Environment:
OS Name: Windows
OS Version: 10.0.18362
class Program
{
static async Task Main()
{
await foreach (var item in new MyAsyncIterator<int>(GetStream()))
{
Console.WriteLine($"Received: {item}");
}
Console.WriteLine($"Done");
}
static async IAsyncEnumerable<int> GetStream()
{
await Task.Delay(1);
try
{
yield return 1;
yield return 2;
}
finally
{
try {}
finally{}
Console.WriteLine("This will not be printed if '_taken++' is not commented");
}
Console.WriteLine("This will not be printed if '_taken++' is not commented");
}
}
public class MyAsyncIterator<T> : IAsyncEnumerable<T>, IAsyncEnumerator<T>
{
private readonly IAsyncEnumerable<T> _source;
private IAsyncEnumerator<T>? _enumerator;
T _current = default!;
public T Current => _current;
public MyAsyncIterator(IAsyncEnumerable<T> source)
{
_source = source;
}
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) => this;
public async ValueTask DisposeAsync()
{
if (_enumerator != null)
{
await _enumerator.DisposeAsync().ConfigureAwait(false);
_enumerator = null;
}
}
private int _taken;
public async ValueTask<bool> MoveNextAsync()
{
_enumerator ??= _source.GetAsyncEnumerator();
if (_taken < 1 && await _enumerator!.MoveNextAsync().ConfigureAwait(false))
{
_taken++; // COMMENTING IT OUT MAKES IT WORK
_current = _enumerator.Current;
return true;
}
return false;
}
}
IL like this is generated after the finally blocks:
IL_0120: ldarg.0 // this
IL_0121: ldfld bool TestAsyncEnum.Program/'<GetStream>d__1'::'<>w__disposeMode'
IL_0126: brfalse.s IL_012a
IL_0128: br.s IL_0136
// [31 17 - 31 63]
IL_012a: ldstr "This will not be printed"
IL_012f: call void [System.Console]System.Console::WriteLine(string)
IL_0134: nop
// [32 13 - 32 14]
IL_0135: nop
IL_0136: endfinally
} // end of finally
So if the enumerator has not enumerated fully w__disposeMode is set to true and code after finally is not executed.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Active/Investigating