用EnumeratorCancellation返回AsyncEnumerable或循环WithCancellation有什么区别 [英] What's the difference between returning AsyncEnumerable with EnumeratorCancellation or looping WithCancellation

查看:46
本文介绍了用EnumeratorCancellation返回AsyncEnumerable或循环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?

推荐答案

根据您应该只使用一次 cancellationToken (直接传递)或使用 WithCancellation ,这些方法的作用相同. WithCancellation IAsyncEnumerable< T> 的扩展方法,接受 CancellationToken 作为参数(它与 ConfigureAwait使用相同的模式).如果使用 [EnumeratorCancellation] ,编译器将生成将令牌传递给 GetAsyncEnumerator 方法

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

为什么有两种不同的方法呢?将令牌直接传递给方法比较简单,但是当您任意处理时,该方法将不起作用IAsyncEnumerable来自其他来源,但仍然希望能够要求取消构成它的所有内容.在在极端情况下,将令牌传递给GetAsyncEnumerator这样做可以避免烧毁"令牌中的令牌.单个枚举将被多次枚举的情况:将其传递给GetAsyncEnumerator,每个传递一个不同的令牌时间.

Why two different ways to do it? Passing the token directly to the method is easier, but it doesn’t work when you’re handed an arbitrary IAsyncEnumerable from some other source but still want to be able to request cancellation of everything that composes it. In corner-cases, it can also be advantageous to pass the token to GetAsyncEnumerator, as doing so avoids "burning in" the token in the case where the single enumerable will be enumerated multiple times: By passing it to GetAsyncEnumerator, a different token can be passed each time.

这篇关于用EnumeratorCancellation返回AsyncEnumerable或循环WithCancellation有什么区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆