用EnumeratorCancellation返回AsyncEnumerable或循环WithCancellation有什么区别 [英] What's the difference between returning AsyncEnumerable with EnumeratorCancellation or looping WithCancellation
问题描述
我有以下方法,可从http流中读取csv文档
I have the following method that reads a csv document from a http stream
public async IAsyncEnumerable<Line> GetLines([EnumeratorCancellation] CancellationToken cancellationToken)
{
HttpResponseMessage response = GetResponse();
using var responseStream = await response.Content.ReadAsStreamAsync();
using var streamReader = new StreamReader(responseStream);
using var csvReader = new CsvReader(streamReader);
while (!cancellationToken.IsCancellationRequested && await csvReader.ReadAsync())
{
yield return csvReader.GetRecord<Line>();
}
}
以及其他使用结果的方法
and a method elsewhere that uses the result
var documentAsyncEnumerable = graphClient.GetLines(cancellationToken);
await foreach (var document in documentAsyncEnumerable.WithCancellation(cancellationToken))
{
// Do something with document
}
我的问题是,我是否应该只在一个地方使用取消令牌?取消令牌应该在产生记录之前执行,还是IAsyncEnumerable.WithCancellation()基本上在做相同的事情?有什么区别?
My question is shouldn I use the cancellation token in just one place? Should the cancellation token be acted upon before yielding the record or is the IAsyncEnumerable.WithCancellation() basically doing the same thing? What is the difference if any?
推荐答案
You should use cancellationToken
only once, passing directly or use WithCancellation
, these methods are doing the same. WithCancellation
is extension method for IAsyncEnumerable<T>
, accepting a CancellationToken
as an argument (it uses the same pattern with ConfigureAwait
). In case of [EnumeratorCancellation]
the compiler generate code that will pass the token to GetAsyncEnumerator
method