Page 1 of 1

Warum geht der AsyncLocal-Wert zwischen IAsyncEnumerable-Ertragspunkten verloren?

Posted: 15 Jan 2025, 15:48
by Guest
Betrachten Sie das folgende Beispiel und insbesondere die „Wrap-Funktion“:

Code: Select all

await foreach (var item in Wrap(Sequence()))
continue;

static IAsyncEnumerable Sequence()
{
return Core();

static async IAsyncEnumerable Core([EnumeratorCancellation] CancellationToken ct = default)
{
yield return 123;
await Task.Delay(TimeSpan.FromSeconds(5), ct);
yield return 456;
}
}

static IAsyncEnumerable Wrap(IAsyncEnumerable source)
{
return Core(source);

static async IAsyncEnumerable Core(IAsyncEnumerable source, [EnumeratorCancellation] CancellationToken ct = default)
{
Test.Context.Value = "Hello world";
await foreach (var value in source.WithCancellation(ct))
{
var before = Test.Context.Value; // Surely this should always be "Hello world", right?
yield return value;
var after = Test.Context.Value; // .. and surely this too?
Console.WriteLine($"Before={before}, after={after}");
}
}
}

static class Test
{
public static readonly AsyncLocal Context = new();
}
Was ich erwartet hatte, war, dass sowohl die erfassten Vorher- als auch Nachher-Werte das zuvor festgelegte „Hallo Welt“ enthalten würden.
Was jedoch passiert, ist, dass für die erste Iteration vor „Hallo Welt“ erfasst wird, nachher dann jedoch null ist.
Für die zweite Iteration dieser Schleife werden beide vor< /code> und after sind null.
  • Warum ist das so? Mir ist nicht ganz klar, was oder warum der Wert von AsyncLocal nach diesem ersten Yield-Punkt gelöscht wird.
  • Was wäre der beste Weg, die Wrap-Funktion so neu zu formulieren? dass der AsyncLocal-Wert für die gesamte Enumeration erhalten bleibt?