Вам гораздо лучше, если вы сможете структурировать свой код так, чтобы использовать преимущества yield return
и await foreach
. Например, этот код делает почти то же самое:
public async Task Consume()
{
var source = ParentMethod();
HandlerTask = Task.Run(async () => { await foreach (var item in source) { Console.WriteLine(item); } });
}
public async IAsyncEnumerable<int> ParentMethod()
{
await Task.Yield();
yield return 13;
await foreach (var item in ChildMethod())
yield return item;
}
private async IAsyncEnumerable<int> ChildMethod()
{
yield return 5;
await Task.Yield();
yield return 10;
}
Однако, если вам действительно нужен «асинхронный c перечислимый источник», вам необходимо сначала распознать одну вещь. TaskCompletionSource<T>
содержит результаты, то есть T
(или исключение). Это действует как контейнер. Результат может быть установлен до того, как задача будет ждать. То же самое относится и к «перечисляемому источнику asyn c» - вам нужно, чтобы он мог хранить результаты до того, как из него будут взяты какие-либо элементы. «Асин c перечислимый источник» должен содержать несколько результатов - в этом случае коллекция .
Итак, что вы на самом деле запрашиваете, так это msgstr "коллекция, которую можно использовать как асинхронный перечислимый". Здесь есть несколько возможностей, но я бы порекомендовал Channel :
public async Task<string> ParentMethod()
{
var source = Channel.CreateUnbounded<int>();
var sourceWriter = source.Writer;
IAsyncEnumerable<int> asyncEnumerable = source.Reader.ReadAllAsync();
HandlerTask = Task.Run(async () => { await foreach (var item in asyncEnumerable) Console.WriteLine(item); });
await Task.Yield();
await sourceWriter.WriteAsync(13);
var r = await ChildMethod(sourceWriter);
sourceWriter.Complete();
return r;
}
private async Task<string> ChildMethod(ChannelWriter<int> sourceWriter)
{
await sourceWriter.WriteAsync(5);
await Task.Yield();
await sourceWriter.WriteAsync(10);
return "hello";
}