我正在尝试使用基于IAsyncEnumerable. 基本上沿着以下路线:
async IAsyncEnumerable<string> ReadAll()
{
var reader = new EventBasedReader();
reader.OnRead => (_, args) => yield return e.Message;
reader.Start();
await reader.WaitUntilAllRead();
}
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用,因为它是产生的事件处理程序,这是不允许的。有没有另一种方法可以编写它以使其作为IAsyncEnumerable.
Ste*_*ary 10
使用基于 IAsyncEnumerable 的 API 包装基于事件的异步订阅 API。
这两者不直接兼容。事件是基于推送的,可枚举(包括异步枚举)是基于拉的。
为了跨越这个鸿沟,您需要一个缓冲区——某个地方来保存事件数据,因为它被推送给您,但在下游代码拉取它之前。
我建议使用 Channels 作为缓冲区。如果您的用例允许,您可以使用无界通道:
IAsyncEnumerable<string> ReadAll()
{
var reader = new EventBasedReader();
var buffer = Channel.CreateUnbounded<TMessage>();
reader.OnRead = async (_, args) => await buffer.Writer.WriteAsync(e.Message);
reader.Start();
CompleteBufferWhenEventsAreDone();
return buffer.Reader.ReadAllAsync();
async void CompleteBufferWhenEventsAreDone()
{
await reader.WaitUntilAllRead();
buffer.Writer.TryComplete();
}
}
Run Code Online (Sandbox Code Playgroud)