C# 如何在丢弃结果的同时等待IAsyncEnumerable

C# 如何在丢弃结果的同时等待IAsyncEnumerable,c#,asynchronous,async-await,iasyncenumerable,C#,Asynchronous,Async Await,Iasyncenumerable,我有一个函数,它返回一个IAsyncEnumerable。我想等待它的完成,但我不在乎任何结果。我只关心调用函数的副作用 我怎样才能轻松地等待IAsyncEnumerable完成,而不使用for循环或将其转换为容器(例如ToListSync)?简短回答:你不能 回答:问 如何在不使用for循环或将其转换为容器(例如ToListSync)的情况下轻松等待IAsyncEnumerable完成 就像问 如果不使用wait或类似.Result或.wait(),我如何等待任务完成 知道IAsyncEnu

我有一个函数,它返回一个
IAsyncEnumerable
。我想
等待它的完成,但我不在乎任何结果。我只关心调用函数的副作用


我怎样才能轻松地
等待
IAsyncEnumerable
完成,而不使用for循环或将其转换为容器(例如
ToListSync
)?

简短回答:你不能


回答:问

如何在不使用for循环或将其转换为容器(例如ToListSync)的情况下轻松等待IAsyncEnumerable完成

就像问

如果不使用
wait
或类似
.Result
.wait()
,我如何等待任务完成

知道
IAsyncEnumerable
何时完成的方法是在迭代器上调用
wait MoveNextAsync()
,然后返回
false
。最简单的方法是

等待foreach(AsyncGenerator()中的var uu);//分号是必需的

简短回答:你不能


回答:问

如何在不使用for循环或将其转换为容器(例如ToListSync)的情况下轻松等待IAsyncEnumerable完成

就像问

如果不使用
wait
或类似
.Result
.wait()
,我如何等待任务完成

知道
IAsyncEnumerable
何时完成的方法是在迭代器上调用
wait MoveNextAsync()
,然后返回
false
。最简单的方法是

等待foreach(AsyncGenerator()中的var uu);//分号是必需的
您可以使用包中的运算符,然后使用扩展方法将生成的
ValueTask
转换为
Task
。为了更加方便,您可以将这两个操作组合到一个扩展方法
ToTask

/// <summary>
/// Retrieves a Task object that represents the completion of this IAsyncEnumerable.
/// </summary>
public static Task ToTask<T>(this IAsyncEnumerable<T> source)
{
    return source.LastOrDefaultAsync().AsTask();
}
//
///检索表示完成此IAsyncEnumerable的任务对象。
/// 
公共静态任务ToTask(此IAsyncEnumerable源)
{
返回source.LastOrDefaultAsync().AsTask();
}
但老实说,手动执行循环更简单,也可能更有效:

public async static Task ToTask<T>(this IAsyncEnumerable<T> source)
{
    await foreach (var _ in source.ConfigureAwait(false)) { }
}
公共异步静态任务ToTask(此IAsyncEnumerable源)
{
wait foreach(source.ConfigureAwait(false))中的var{}
}
LastOrDefaultAsync
操作符将在可枚举生命周期内在内存中保留最后发出的元素,这可能会防止元素被及时垃圾收集。您可以通过在查询中包含来自包的运算符来防止这种情况发生,但我认为这太麻烦了。

您可以使用来自包的运算符,然后使用扩展方法将结果
ValueTask
转换为
任务。为了更加方便,您可以将这两个操作组合到一个扩展方法
ToTask

/// <summary>
/// Retrieves a Task object that represents the completion of this IAsyncEnumerable.
/// </summary>
public static Task ToTask<T>(this IAsyncEnumerable<T> source)
{
    return source.LastOrDefaultAsync().AsTask();
}
//
///检索表示完成此IAsyncEnumerable的任务对象。
/// 
公共静态任务ToTask(此IAsyncEnumerable源)
{
返回source.LastOrDefaultAsync().AsTask();
}
但老实说,手动执行循环更简单,也可能更有效:

public async static Task ToTask<T>(this IAsyncEnumerable<T> source)
{
    await foreach (var _ in source.ConfigureAwait(false)) { }
}
公共异步静态任务ToTask(此IAsyncEnumerable源)
{
wait foreach(source.ConfigureAwait(false))中的var{}
}

LastOrDefaultAsync
操作符将在可枚举生命周期内在内存中保留最后发出的元素,这可能会防止元素被及时垃圾收集。您可以通过在查询中包含来自包的运算符来防止这种情况的发生,但我认为这太麻烦了。

您需要对其进行循环。直到最后一次调用
MoveNextAsync
返回一个
ValueTask
并以
false
结束时,您才知道它已“完成”。直到最后一次调用
MoveNextAsync
返回一个
ValueTask
并以
false