-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should / how should CancellationToken show up in IAsyncEnumerable-related interfaces? #27858
Comments
We discussed this again at length in C# language design, and came to the conclusion that we should add back the CancellationToken argument to GetAsyncEnumerator: That means we change this: public interface IAsyncEnumerable<out T>
{
IAsyncEnumerator<T> GetAsyncEnumerator();
} to this: public interface IAsyncEnumerable<out T>
{
IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default);
} The language/compiler will do a minimal amount to support this:
This isn't a perfect solution, but it's the best of the options we're aware of, it enables composability and combinators and the like, and it leaves the door open for the compiler to do more in the future if it proves important. This leads to the following approach/guidance for developers:
internal static async IAsyncEnumerable<Stuff> EnumerateStuff(CancellationToken cancellationToken)
{
await foreach (OtherStuff item in EnumerateOtherStuff(CancellationToken))
{
yield return GetStuff(item);
}
}
public static async IAsyncEnumerable<Stuff> EnumerateStuff() =>
new EnumerateStuffIterator();
internal sealed class EnumerateStuffIterator : IAsyncEnumerable<Stuff>
{
public async IAsyncEnumerator<Stuff> GetAsyncEnumerator(CancellationToken cancellationToken)
{
await foreach (OtherStuff item in EnumerateOtherStuff(cancellationToken))
{
yield return GetStuff(item);
}
}
} While a small amount of additional boilerplate, this will then compose nicely with an ecosystem that provides the token to the interface call. One additional downside to this "easy" approach is it results in one more allocation that we could otherwise get away with, but our hope is that for an async iteration that one additional allocation should be nominal, and for critical things where it isn't, it's still possible to avoid it by writing the state machine manually. I will open a separate issue for cc: @onovotny, @jcouv, @terrajobst, @bartonjs |
@stephentoub Thank you for posting details. Could you make the last code sample more explicit regarding how the |
It should have been a parameter. Fixed. |
Since the rest of the support is set, and since we've now merged these interfaces in support of .NET Core 3.0 previews, I'm opening a separate issue specifically to cover whether we should make any changes related to cancellation.
See https://github.com/dotnet/corefx/issues/32640#issuecomment-436316907.
The text was updated successfully, but these errors were encountered: