public class Playground : UnitTestsBase
{
/// <inheritdoc />
public Playground(ITestOutputHelper output) : base(output)
{
}
[Fact]
public async Task Test1()
{
var invoked = false;
var ienu = new DelegateAsyncEnumerable<IEnumerable<string>>(async ct =>
{
if (invoked) return null;
await Task.Yield();
IEnumerable<string> x = new[] {"abc", "def", "ghi", "jkl"};
invoked = true;
return Tuple.Create(x.Select(a => a + "a"), true);
});
var y = ienu.SelectMany(t => t.ToAsyncEnumerable());
var z = await y.Take(4).ToArray();
ShallowTrace(z);
Assert.DoesNotContain(null, z);
}
}
The assertion fails. If I either change Take(4) to Take(3), change Select invocation to x.Select((a, i) => a + "a"), or remove await Task.Yield(); line, the test passes.
Test case
The assertion fails. If I either change
Take(4)
toTake(3)
, changeSelect
invocation tox.Select((a, i) => a + "a")
, or removeawait Task.Yield();
line, the test passes.It seems that there is a strange interaction between the underlying
SelectArrayIterator<TSource, TResult>
and thread-context switches. I got a rough idea when looking atIterator<TSource>.GetEnumerator
, but would take another time to dig it deeper.Related code in library: https://github.com/CXuesong/WikiClientLibrary/blob/435681dad887b160a475ca2c40b6e25d67990d06/WikiClientLibrary/Flow/Board.cs#L108-L111