AsyncEnumerableExtensions.cs 5.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections.Generic;
  5. using System.Runtime.CompilerServices;
  6. namespace System.Threading.Tasks
  7. {
  8. public static class AsyncEnumerableExtensions
  9. {
  10. #if !BCL_HAS_CONFIGUREAWAIT // https://github.com/dotnet/coreclr/pull/21939
  11. /// <summary>Configures how awaits on the tasks returned from an async iteration will be performed.</summary>
  12. /// <typeparam name="T">The type of the objects being iterated.</typeparam>
  13. /// <param name="source">The source enumerable being iterated.</param>
  14. /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
  15. /// <returns>The configured enumerable.</returns>
  16. public static ConfiguredCancelableAsyncEnumerable<T> ConfigureAwait<T>(
  17. this IAsyncEnumerable<T> source, bool continueOnCapturedContext) =>
  18. new ConfiguredCancelableAsyncEnumerable<T>(source, continueOnCapturedContext, cancellationToken: default);
  19. /// <summary>Sets the <see cref="CancellationToken"/> to be passed to <see cref="IAsyncEnumerable{T}.GetAsyncEnumerator(CancellationToken)"/> when iterating.</summary>
  20. /// <typeparam name="T">The type of the objects being iterated.</typeparam>
  21. /// <param name="source">The source enumerable being iterated.</param>
  22. /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
  23. /// <returns>The configured enumerable.</returns>
  24. public static ConfiguredCancelableAsyncEnumerable<T> WithCancellation<T>(
  25. this IAsyncEnumerable<T> source, CancellationToken cancellationToken) =>
  26. new ConfiguredCancelableAsyncEnumerable<T>(source, continueOnCapturedContext: true, cancellationToken);
  27. #elif !REFERENCE_ASSEMBLY
  28. // we need to carry an impl that delegates to the BCL version of these
  29. /// <summary>Configures how awaits on the tasks returned from an async iteration will be performed.</summary>
  30. /// <typeparam name="T">The type of the objects being iterated.</typeparam>
  31. /// <param name="source">The source enumerable being iterated.</param>
  32. /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
  33. /// <returns>The configured enumerable.</returns>
  34. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  35. public static ConfiguredCancelableAsyncEnumerable<T> ConfigureAwait<T>(
  36. this IAsyncEnumerable<T> source, bool continueOnCapturedContext) => TaskExtensions.ConfigureAwait(source, continueOnCapturedContext);
  37. /// <summary>Sets the <see cref="CancellationToken"/> to be passed to <see cref="IAsyncEnumerable{T}.GetAsyncEnumerator(CancellationToken)"/> when iterating.</summary>
  38. /// <typeparam name="T">The type of the objects being iterated.</typeparam>
  39. /// <param name="source">The source enumerable being iterated.</param>
  40. /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
  41. /// <returns>The configured enumerable.</returns>
  42. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  43. public static ConfiguredCancelableAsyncEnumerable<T> WithCancellation<T>(
  44. this IAsyncEnumerable<T> source, CancellationToken cancellationToken) => TaskExtensions.WithCancellation(source, cancellationToken);
  45. #else
  46. // Reference assembly, these won't be emmited, but keep these internal so we can compile
  47. /// <summary>Configures how awaits on the tasks returned from an async iteration will be performed.</summary>
  48. /// <typeparam name="T">The type of the objects being iterated.</typeparam>
  49. /// <param name="source">The source enumerable being iterated.</param>
  50. /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
  51. /// <returns>The configured enumerable.</returns>
  52. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  53. internal static ConfiguredCancelableAsyncEnumerable<T> ConfigureAwait<T>(
  54. this IAsyncEnumerable<T> source, bool continueOnCapturedContext) => TaskExtensions.ConfigureAwait(source, continueOnCapturedContext);
  55. /// <summary>Sets the <see cref="CancellationToken"/> to be passed to <see cref="IAsyncEnumerable{T}.GetAsyncEnumerator(CancellationToken)"/> when iterating.</summary>
  56. /// <typeparam name="T">The type of the objects being iterated.</typeparam>
  57. /// <param name="source">The source enumerable being iterated.</param>
  58. /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param>
  59. /// <returns>The configured enumerable.</returns>
  60. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  61. internal static ConfiguredCancelableAsyncEnumerable<T> WithCancellation<T>(
  62. this IAsyncEnumerable<T> source, CancellationToken cancellationToken) => TaskExtensions.WithCancellation(source, cancellationToken);
  63. #endif
  64. public static ConfiguredCancelableAsyncEnumerable<T>.Enumerator GetConfiguredAsyncEnumerator<T>(this IAsyncEnumerable<T> enumerable, CancellationToken cancellationToken, bool continueOnCapturedContext)
  65. {
  66. #if REFERENCE_ASSEMBLY
  67. return default;
  68. #else
  69. return ConfigureAwait(enumerable, continueOnCapturedContext).WithCancellation(cancellationToken).GetAsyncEnumerator();
  70. #endif
  71. }
  72. }
  73. }