1
0
Эх сурвалжийг харах

Switch to IAsyncDisposable.

Bart De Smet 8 жил өмнө
parent
commit
2659fb7e97
52 өөрчлөгдсөн 659 нэмэгдсэн , 346 устгасан
  1. 15 2
      Ix.NET/Source/System.Interactive.Async/Aggregate.cs
  2. 23 3
      Ix.NET/Source/System.Interactive.Async/AnyAll.cs
  3. 44 18
      Ix.NET/Source/System.Interactive.Async/AppendPrepend.cs
  4. 7 1
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerableHelpers.cs
  5. 7 3
      Ix.NET/Source/System.Interactive.Async/AsyncIterator.cs
  6. 70 10
      Ix.NET/Source/System.Interactive.Async/Average.cs
  7. 5 5
      Ix.NET/Source/System.Interactive.Async/Buffer.cs
  8. 16 11
      Ix.NET/Source/System.Interactive.Async/Catch.cs
  9. 22 11
      Ix.NET/Source/System.Interactive.Async/Concatenate.cs
  10. 11 8
      Ix.NET/Source/System.Interactive.Async/Create.cs
  11. 5 5
      Ix.NET/Source/System.Interactive.Async/DefaultIfEmpty.cs
  12. 17 0
      Ix.NET/Source/System.Interactive.Async/Disposables.cs
  13. 42 21
      Ix.NET/Source/System.Interactive.Async/Distinct.cs
  14. 4 4
      Ix.NET/Source/System.Interactive.Async/Do.cs
  15. 14 2
      Ix.NET/Source/System.Interactive.Async/ElementAt.cs
  16. 5 5
      Ix.NET/Source/System.Interactive.Async/Except.cs
  17. 10 6
      Ix.NET/Source/System.Interactive.Async/Expand.cs
  18. 4 4
      Ix.NET/Source/System.Interactive.Async/Finally.cs
  19. 16 2
      Ix.NET/Source/System.Interactive.Async/First.cs
  20. 8 1
      Ix.NET/Source/System.Interactive.Async/ForEach.cs
  21. 7 6
      Ix.NET/Source/System.Interactive.Async/Generate.cs
  22. 1 4
      Ix.NET/Source/System.Interactive.Async/GroupJoin.cs
  23. 9 9
      Ix.NET/Source/System.Interactive.Async/Grouping.cs
  24. 1 1
      Ix.NET/Source/System.Interactive.Async/IAsyncEnumerator.cs
  25. 4 4
      Ix.NET/Source/System.Interactive.Async/IgnoreElements.cs
  26. 4 4
      Ix.NET/Source/System.Interactive.Async/Intersect.cs
  27. 4 4
      Ix.NET/Source/System.Interactive.Async/Join.cs
  28. 16 2
      Ix.NET/Source/System.Interactive.Async/Last.cs
  29. 24 3
      Ix.NET/Source/System.Interactive.Async/Lookup.cs
  30. 7 1
      Ix.NET/Source/System.Interactive.Async/Min.cs
  31. 6 6
      Ix.NET/Source/System.Interactive.Async/OnErrorResumeNext.cs
  32. 4 4
      Ix.NET/Source/System.Interactive.Async/OrderedAsyncEnumerable.cs
  33. 5 5
      Ix.NET/Source/System.Interactive.Async/Repeat.cs
  34. 3 3
      Ix.NET/Source/System.Interactive.Async/Reverse.cs
  35. 8 8
      Ix.NET/Source/System.Interactive.Async/Scan.cs
  36. 14 14
      Ix.NET/Source/System.Interactive.Async/Select.cs
  37. 40 24
      Ix.NET/Source/System.Interactive.Async/SelectMany.cs
  38. 24 10
      Ix.NET/Source/System.Interactive.Async/SequenceEqual.cs
  39. 15 2
      Ix.NET/Source/System.Interactive.Async/Single.cs
  40. 16 16
      Ix.NET/Source/System.Interactive.Async/Skip.cs
  41. 17 17
      Ix.NET/Source/System.Interactive.Async/Take.cs
  42. 27 21
      Ix.NET/Source/System.Interactive.Async/ToAsyncEnumerable.cs
  43. 6 5
      Ix.NET/Source/System.Interactive.Async/ToObservable.cs
  44. 4 4
      Ix.NET/Source/System.Interactive.Async/Using.cs
  45. 12 12
      Ix.NET/Source/System.Interactive.Async/Where.cs
  46. 5 5
      Ix.NET/Source/System.Interactive.Async/Zip.cs
  47. 4 3
      Ix.NET/Source/Tests/AsyncTests.Bugs.cs
  48. 3 3
      Ix.NET/Source/Tests/AsyncTests.Conversions.cs
  49. 10 10
      Ix.NET/Source/Tests/AsyncTests.Creation.cs
  50. 2 2
      Ix.NET/Source/Tests/AsyncTests.Exceptions.cs
  51. 10 10
      Ix.NET/Source/Tests/AsyncTests.Single.cs
  52. 2 2
      Ix.NET/Source/Tests/AsyncTests.cs

+ 15 - 2
Ix.NET/Source/System.Interactive.Async/Aggregate.cs

@@ -81,7 +81,9 @@ namespace System.Linq
         {
             var acc = seed;
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -89,6 +91,10 @@ namespace System.Linq
                     acc = accumulator(acc, e.Current);
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
 
             return resultSelector(acc);
         }
@@ -98,7 +104,9 @@ namespace System.Linq
             var first = true;
             var acc = default(TSource);
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -107,6 +115,11 @@ namespace System.Linq
                     first = false;
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
             if (first)
                 throw new InvalidOperationException(Strings.NO_ELEMENTS);
             return acc;

+ 23 - 3
Ix.NET/Source/System.Interactive.Async/AnyAll.cs

@@ -65,15 +65,23 @@ namespace System.Linq
             if (source == null)
                 throw new ArgumentNullException(nameof(source));
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 return await e.MoveNextAsync(cancellationToken).ConfigureAwait(false);
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
 
         private static async Task<bool> All_<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -82,12 +90,19 @@ namespace System.Linq
                         return false;
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
             return true;
         }
 
         private static async Task<bool> Any_<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -96,6 +111,11 @@ namespace System.Linq
                         return true;
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
             return false;
         }
     }

+ 44 - 18
Ix.NET/Source/System.Interactive.Async/AppendPrepend.cs

@@ -69,21 +69,24 @@ namespace System.Linq
                     return true;
                 }
 
-                enumerator?.Dispose();
-                enumerator = null;
+                if (enumerator != null)
+                {
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
+                    enumerator = null;
+                }
 
                 return false;
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             public abstract Task<TSource[]> ToArrayAsync(CancellationToken cancellationToken);
@@ -151,7 +154,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
 
@@ -201,7 +204,9 @@ namespace System.Linq
                 }
                 else
                 {
-                    using (var en = source.GetAsyncEnumerator())
+                    var en = source.GetAsyncEnumerator();
+
+                    try
                     {
                         while (await en.MoveNextAsync(cancellationToken)
                                        .ConfigureAwait(false))
@@ -210,6 +215,10 @@ namespace System.Linq
                             ++index;
                         }
                     }
+                    finally
+                    {
+                        await en.DisposeAsync().ConfigureAwait(false);
+                    }
                 }
 
                 if (appending)
@@ -231,7 +240,9 @@ namespace System.Linq
                 }
 
 
-                using (var en = source.GetAsyncEnumerator())
+                var en = source.GetAsyncEnumerator();
+
+                try
                 {
                     while (await en.MoveNextAsync(cancellationToken)
                                    .ConfigureAwait(false))
@@ -239,6 +250,10 @@ namespace System.Linq
                         list.Add(en.Current);
                     }
                 }
+                finally
+                {
+                    await en.DisposeAsync().ConfigureAwait(false);
+                }
 
                 if (appending)
                 {
@@ -330,7 +345,7 @@ namespace System.Linq
             int mode;
             IEnumerator<TSource> appendedEnumerator;
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (appendedEnumerator != null)
                 {
@@ -338,7 +353,7 @@ namespace System.Linq
                     appendedEnumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -399,7 +414,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
 
@@ -435,7 +450,9 @@ namespace System.Linq
                 }
                 else
                 {
-                    using (var en = source.GetAsyncEnumerator())
+                    var en = source.GetAsyncEnumerator();
+
+                    try
                     {
                         while (await en.MoveNextAsync(cancellationToken)
                                        .ConfigureAwait(false))
@@ -444,6 +461,10 @@ namespace System.Linq
                             ++index;
                         }
                     }
+                    finally
+                    {
+                        await en.DisposeAsync().ConfigureAwait(false);
+                    }
                 }
 
                 index = array.Length;
@@ -465,7 +486,9 @@ namespace System.Linq
                     list.Add(n.Item);
                 }
 
-                using (var en = source.GetAsyncEnumerator())
+                var en = source.GetAsyncEnumerator();
+
+                try
                 {
                     while (await en.MoveNextAsync(cancellationToken)
                                    .ConfigureAwait(false))
@@ -473,15 +496,18 @@ namespace System.Linq
                         list.Add(en.Current);
                     }
                 }
-                
-                if (appended != null)
+                finally
                 {
+                    await en.DisposeAsync().ConfigureAwait(false);
+                }
 
-                    using (var en = appended.GetEnumerator())
+                if (appended != null)
+                {
+                    using (var en2 = appended.GetEnumerator())
                     {
-                        while (en.MoveNext())
+                        while (en2.MoveNext())
                         {
-                            list.Add(en.Current);
+                            list.Add(en2.Current);
                         }
                     }
                 }

+ 7 - 1
Ix.NET/Source/System.Interactive.Async/AsyncEnumerableHelpers.cs

@@ -43,7 +43,9 @@ namespace System.Collections.Generic
             }
             else
             {
-                using (var en = source.GetAsyncEnumerator())
+                var en = source.GetAsyncEnumerator();
+
+                try
                 {
                     if (await en.MoveNextAsync(cancellationToken)
                                 .ConfigureAwait(false))
@@ -92,6 +94,10 @@ namespace System.Collections.Generic
                         return result;
                     }
                 }
+                finally
+                {
+                    await en.DisposeAsync().ConfigureAwait(false);
+                }
             }
 
             result.length = 0;

+ 7 - 3
Ix.NET/Source/System.Interactive.Async/AsyncIterator.cs

@@ -10,6 +10,8 @@ namespace System.Linq
 {
     public static partial class AsyncEnumerable
     {
+        private static readonly Task CompletedTask = Task.FromResult(true); // TODO: Change to Task.CompletedTask when all build targets allow.
+
         internal abstract class AsyncIterator<TSource> : IAsyncEnumerable<TSource>, IAsyncEnumerator<TSource>
         {
             private readonly int threadId;
@@ -40,7 +42,7 @@ namespace System.Linq
                 }
                 catch
                 {
-                    enumerator.Dispose();
+                    enumerator.DisposeAsync(); // REVIEW: fire-and-forget?
                     throw;
                 }
 
@@ -48,7 +50,7 @@ namespace System.Linq
             }
 
 
-            public virtual void Dispose()
+            public virtual Task DisposeAsync()
             {
                 if (cancellationTokenSource != null)
                 {
@@ -61,6 +63,8 @@ namespace System.Linq
 
                 current = default(TSource);
                 state = AsyncIteratorState.Disposed;
+
+                return CompletedTask;
             }
 
             public TSource Current
@@ -96,7 +100,7 @@ namespace System.Linq
                 catch
                 {
                     currentIsInvalid = true;
-                    Dispose();
+                    await DisposeAsync().ConfigureAwait(false);
                     throw;
                 }
             }

+ 70 - 10
Ix.NET/Source/System.Interactive.Async/Average.cs

@@ -383,7 +383,9 @@ namespace System.Linq
 
         private static async Task<double> Average_(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (!await e.MoveNextAsync(cancellationToken)
                             .ConfigureAwait(false))
@@ -405,11 +407,17 @@ namespace System.Linq
 
                 return (double)sum/count;
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
 
         private static async Task<double?> Average_(IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -437,13 +445,19 @@ namespace System.Linq
                     }
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
 
             return null;
         }
 
         private static async Task<double> Average_(IAsyncEnumerable<long> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (!await e.MoveNextAsync(cancellationToken)
                             .ConfigureAwait(false))
@@ -465,11 +479,17 @@ namespace System.Linq
 
                 return (double)sum/count;
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
 
         private static async Task<double?> Average_(IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -497,13 +517,19 @@ namespace System.Linq
                     }
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
 
             return null;
         }
 
         private static async Task<double> Average_(IAsyncEnumerable<double> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (!await e.MoveNextAsync(cancellationToken)
                             .ConfigureAwait(false))
@@ -525,11 +551,17 @@ namespace System.Linq
 
                 return sum/count;
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
 
         private static async Task<double?> Average_(IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -557,13 +589,19 @@ namespace System.Linq
                     }
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
 
             return null;
         }
 
         private static async Task<float> Average_(IAsyncEnumerable<float> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (!await e.MoveNextAsync(cancellationToken)
                             .ConfigureAwait(false))
@@ -582,11 +620,17 @@ namespace System.Linq
 
                 return (float)(sum/count);
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
 
         private static async Task<float?> Average_(IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -614,13 +658,19 @@ namespace System.Linq
                     }
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
 
             return null;
         }
 
         private static async Task<decimal> Average_(IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (!await e.MoveNextAsync(cancellationToken)
                             .ConfigureAwait(false))
@@ -639,11 +689,17 @@ namespace System.Linq
 
                 return sum/count;
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
 
         private static async Task<decimal?> Average_(IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -668,6 +724,10 @@ namespace System.Linq
                     }
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
 
             return null;
         }

+ 5 - 5
Ix.NET/Source/System.Interactive.Async/Buffer.cs

@@ -58,17 +58,17 @@ namespace System.Linq
                 return new BufferAsyncIterator<TSource>(source, count, skip);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
                 buffers = null;
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -113,7 +113,7 @@ namespace System.Linq
                                     continue; // loop
                                 }
                                 stopped = true;
-                                enumerator.Dispose();
+                                await enumerator.DisposeAsync().ConfigureAwait(false);
                                 enumerator = null;
 
                                 continue; // loop
@@ -131,7 +131,7 @@ namespace System.Linq
                         break; // case
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 16 - 11
Ix.NET/Source/System.Interactive.Async/Catch.cs

@@ -76,15 +76,15 @@ namespace System.Linq
                 return new CatchAsyncIterator<TSource, TException>(source, handler);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -119,7 +119,12 @@ namespace System.Linq
                                     // current behavior
                                     var err = handler(ex)
                                         .GetAsyncEnumerator();
-                                    enumerator?.Dispose();
+
+                                    if (enumerator != null)
+                                    {
+                                        await enumerator.DisposeAsync().ConfigureAwait(false);
+                                    }
+
                                     enumerator = err;
                                     isDone = true;
                                     continue; // loop so we hit the catch state
@@ -139,7 +144,7 @@ namespace System.Linq
                         break; // case
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -165,7 +170,7 @@ namespace System.Linq
                 return new CatchAsyncIterator<TSource>(sources);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (sourcesEnumerator != null)
                 {
@@ -175,13 +180,13 @@ namespace System.Linq
 
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
                 error = null;
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -222,7 +227,7 @@ namespace System.Linq
                             catch (Exception ex)
                             {
                                 // Done with the current one, go to the next
-                                enumerator.Dispose();
+                                await enumerator.DisposeAsync().ConfigureAwait(false);
                                 enumerator = null;
                                 error = ExceptionDispatchInfo.Capture(ex);
                                 continue;
@@ -233,8 +238,8 @@ namespace System.Linq
 
                         break; // case
                 }
-                
-                Dispose();
+
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 22 - 11
Ix.NET/Source/System.Interactive.Async/Concatenate.cs

@@ -61,7 +61,7 @@ namespace System.Linq
                 return new ConcatEnumerableAsyncIterator<TSource>(source);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (outerEnumerator != null)
                 {
@@ -71,11 +71,11 @@ namespace System.Linq
 
                 if (currentEnumerator != null)
                 {
-                    currentEnumerator.Dispose();
+                    await currentEnumerator.DisposeAsync().ConfigureAwait(false);
                     currentEnumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             // State machine vars
@@ -104,7 +104,11 @@ namespace System.Linq
                                 if (outerEnumerator.MoveNext())
                                 {
                                     // make sure we dispose the previous one if we're about to replace it
-                                    currentEnumerator?.Dispose();
+                                    if (currentEnumerator != null)
+                                    {
+                                        await currentEnumerator.DisposeAsync().ConfigureAwait(false);
+                                    }
+
                                     currentEnumerator = outerEnumerator.Current.GetAsyncEnumerator();
                                    
                                     mode = State_While;
@@ -125,7 +129,7 @@ namespace System.Linq
                    
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
@@ -191,7 +195,10 @@ namespace System.Linq
                     {
                         break;
                     }
-                    using (var e = source.GetAsyncEnumerator())
+
+                    var e = source.GetAsyncEnumerator();
+
+                    try
                     {
                         while (await e.MoveNextAsync(cancellationToken)
                                       .ConfigureAwait(false))
@@ -199,6 +206,10 @@ namespace System.Linq
                             list.Add(e.Current);
                         }
                     }
+                    finally
+                    {
+                        await e.DisposeAsync().ConfigureAwait(false);
+                    }
                 }
 
                 return list;
@@ -229,15 +240,15 @@ namespace System.Linq
                 return count;
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -265,12 +276,12 @@ namespace System.Linq
                         var next = GetAsyncEnumerable(counter++ - 1);
                         if (next != null)
                         {
-                            enumerator.Dispose();
+                            await enumerator.DisposeAsync().ConfigureAwait(false);
                             enumerator = next.GetAsyncEnumerator();
                             continue;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                     }
                 }

+ 11 - 8
Ix.NET/Source/System.Interactive.Async/Create.cs

@@ -19,7 +19,7 @@ namespace System.Linq
             return new AnonymousAsyncEnumerable<T>(getEnumerator);
         }
 
-        public static IAsyncEnumerator<T> CreateEnumerator<T>(Func<Task<bool>> moveNext, Func<T> current, Action dispose)
+        public static IAsyncEnumerator<T> CreateEnumerator<T>(Func<Task<bool>> moveNext, Func<T> current, Func<Task> dispose)
         {
             if (moveNext == null)
                 throw new ArgumentNullException(nameof(moveNext));
@@ -29,7 +29,7 @@ namespace System.Linq
             return new AnonymousAsyncIterator<T>(moveNext, current, dispose);
         }
 
-        private static IAsyncEnumerator<T> CreateEnumerator<T>(Func<TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Action dispose)
+        private static IAsyncEnumerator<T> CreateEnumerator<T>(Func<TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Func<Task> dispose)
         {
             var self = new AnonymousAsyncIterator<T>(
                 async () =>
@@ -71,11 +71,11 @@ namespace System.Linq
         private sealed class AnonymousAsyncIterator<T> : AsyncIterator<T>
         {
             private readonly Func<T> currentFunc;
-            private readonly Action dispose;
+            private readonly Func<Task> dispose;
             private readonly Func<Task<bool>> moveNext;
 
 
-            public AnonymousAsyncIterator(Func<Task<bool>> moveNext, Func<T> currentFunc, Action dispose)
+            public AnonymousAsyncIterator(Func<Task<bool>> moveNext, Func<T> currentFunc, Func<Task> dispose)
             {
                 Debug.Assert(moveNext != null);
 
@@ -92,11 +92,14 @@ namespace System.Linq
                 throw new NotSupportedException("AnonymousAsyncIterator cannot be cloned. It is only intended for use as an iterator.");
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
-                dispose?.Invoke();
+                if (dispose != null)
+                {
+                    await dispose().ConfigureAwait(false);
+                }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -114,7 +117,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 5 - 5
Ix.NET/Source/System.Interactive.Async/DefaultIfEmpty.cs

@@ -48,15 +48,15 @@ namespace System.Linq
                 return new DefaultIfEmptyAsyncIterator<TSource>(source, defaultValue);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -74,7 +74,7 @@ namespace System.Linq
                         else
                         {
                             current = defaultValue;
-                            enumerator.Dispose();
+                            await enumerator.DisposeAsync().ConfigureAwait(false);
                             enumerator = null;
 
                             state = AsyncIteratorState.Disposed; 
@@ -91,7 +91,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
 

+ 17 - 0
Ix.NET/Source/System.Interactive.Async/Disposables.cs

@@ -32,6 +32,11 @@ namespace System.Linq
         {
             return new BinaryDisposable(d1, d2);
         }
+
+        public static IDisposable Create(Action action)
+        {
+            return new AnonymousDisposable(action);
+        }
     }
 
     class BinaryDisposable : IDisposable
@@ -60,4 +65,16 @@ namespace System.Linq
             }
         }
     }
+
+    class AnonymousDisposable : IDisposable
+    {
+        private Action _action;
+
+        public AnonymousDisposable(Action action)
+        {
+            _action = action;
+        }
+
+        public void Dispose() => _action();
+    }
 }

+ 42 - 21
Ix.NET/Source/System.Interactive.Async/Distinct.cs

@@ -139,7 +139,10 @@ namespace System.Linq
 
                 var count = 0;
                 var s = new Set<TKey>(comparer);
-                using (var enu = source.GetAsyncEnumerator())
+
+                var enu = source.GetAsyncEnumerator();
+
+                try
                 {
                     while (await enu.MoveNextAsync()
                                     .ConfigureAwait(false))
@@ -151,6 +154,10 @@ namespace System.Linq
                         }
                     }
                 }
+                finally
+                {
+                    await enu.DisposeAsync().ConfigureAwait(false);
+                }
 
                 return count;
             }
@@ -160,16 +167,16 @@ namespace System.Linq
                 return new DistinctAsyncIterator<TSource, TKey>(source, keySelector, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                     set = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -181,7 +188,7 @@ namespace System.Linq
                         if (!await enumerator.MoveNextAsync()
                                              .ConfigureAwait(false))
                         {
-                            Dispose();
+                            await DisposeAsync().ConfigureAwait(false);
                             return false;
                         }
 
@@ -207,7 +214,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
 
@@ -215,7 +222,10 @@ namespace System.Linq
             {
                 var s = new Set<TKey>(comparer);
                 var r = new List<TSource>();
-                using (var enu = source.GetAsyncEnumerator())
+
+                var enu = source.GetAsyncEnumerator();
+
+                try
                 {
                     while (await enu.MoveNextAsync(cancellationToken)
                                     .ConfigureAwait(false))
@@ -227,6 +237,10 @@ namespace System.Linq
                         }
                     }
                 }
+                finally
+                {
+                    await enu.DisposeAsync().ConfigureAwait(false);
+                }
 
                 return r;
             }
@@ -273,16 +287,16 @@ namespace System.Linq
                 return new DistinctAsyncIterator<TSource>(source, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                     set = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -294,7 +308,7 @@ namespace System.Linq
                         if (!await enumerator.MoveNextAsync()
                                              .ConfigureAwait(false))
                         {
-                            Dispose();
+                            await DisposeAsync().ConfigureAwait(false);
                             return false;
                         }
 
@@ -320,14 +334,17 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
 
             private async Task<Set<TSource>> FillSet(CancellationToken cancellationToken)
             {
                 var s = new Set<TSource>(comparer);
-                using (var enu = source.GetAsyncEnumerator())
+
+                var enu = source.GetAsyncEnumerator();
+
+                try
                 {
                     while (await enu.MoveNextAsync(cancellationToken)
                                     .ConfigureAwait(false))
@@ -335,6 +352,10 @@ namespace System.Linq
                         s.Add(enu.Current);
                     }
                 }
+                finally
+                {
+                    await enu.DisposeAsync().ConfigureAwait(false);
+                }
 
                 return s;
             }
@@ -363,16 +384,16 @@ namespace System.Linq
                 return new DistinctUntilChangedAsyncIterator<TSource>(source, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                     currentValue = default(TSource);
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -407,7 +428,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -434,16 +455,16 @@ namespace System.Linq
                 return new DistinctUntilChangedAsyncIterator<TSource, TKey>(source, keySelector, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                     currentKeyValue = default(TKey);
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -479,7 +500,7 @@ namespace System.Linq
                         break; // case
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 4 - 4
Ix.NET/Source/System.Interactive.Async/Do.cs

@@ -99,15 +99,15 @@ namespace System.Linq
                 return new DoAsyncIterator<TSource>(source, onNext, onError, onCompleted);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -143,7 +143,7 @@ namespace System.Linq
 
                         onCompleted?.Invoke();
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 14 - 2
Ix.NET/Source/System.Interactive.Async/ElementAt.cs

@@ -58,7 +58,9 @@ namespace System.Linq
 
             if (index >= 0)
             {
-                using (var e = source.GetAsyncEnumerator())
+                var e = source.GetAsyncEnumerator();
+
+                try
                 {
                     while (await e.MoveNextAsync(cancellationToken)
                                   .ConfigureAwait(false))
@@ -71,6 +73,10 @@ namespace System.Linq
                         index--;
                     }
                 }
+                finally
+                {
+                    await e.DisposeAsync().ConfigureAwait(false);
+                }
             }
 
             throw new ArgumentOutOfRangeException(nameof(index));
@@ -80,7 +86,9 @@ namespace System.Linq
         {
             if (index >= 0)
             {
-                using (var e = source.GetAsyncEnumerator())
+                var e = source.GetAsyncEnumerator();
+
+                try
                 {
                     while (await e.MoveNextAsync(cancellationToken)
                                   .ConfigureAwait(false))
@@ -93,6 +101,10 @@ namespace System.Linq
                         index--;
                     }
                 }
+                finally
+                {
+                    await e.DisposeAsync().ConfigureAwait(false);
+                }
             }
 
             return default(TSource);

+ 5 - 5
Ix.NET/Source/System.Interactive.Async/Except.cs

@@ -62,17 +62,17 @@ namespace System.Linq
                 return new ExceptAsyncIterator<TSource>(first, second, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (firstEnumerator != null)
                 {
-                    firstEnumerator.Dispose();
+                    await firstEnumerator.DisposeAsync().ConfigureAwait(false);
                     firstEnumerator = null;
                 }
 
                 set = null;
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -118,9 +118,9 @@ namespace System.Linq
                             }
 
                         } while (moveNext);
-                        
 
-                        Dispose();
+
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 10 - 6
Ix.NET/Source/System.Interactive.Async/Expand.cs

@@ -44,17 +44,17 @@ namespace System.Linq
                 return new ExpandAsyncIterator<TSource>(source, selector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
                 queue = null;
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -77,7 +77,11 @@ namespace System.Linq
                                 {
                                     var src = queue.Dequeue();
 
-                                    enumerator?.Dispose();
+                                    if (enumerator != null)
+                                    {
+                                        await enumerator.DisposeAsync().ConfigureAwait(false);
+                                    }
+
                                     enumerator = src.GetAsyncEnumerator();
 
                                     continue; // loop
@@ -95,14 +99,14 @@ namespace System.Linq
                                 current = item;
                                 return true;
                             }
-                            enumerator.Dispose();
+                            await enumerator.DisposeAsync().ConfigureAwait(false);
                             enumerator = null;
                         }
 
                         break; // case
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 4 - 4
Ix.NET/Source/System.Interactive.Async/Finally.cs

@@ -42,17 +42,17 @@ namespace System.Linq
                 return new FinallyAsyncIterator<TSource>(source, finallyAction);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
 
                     finallyAction();
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -72,7 +72,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 16 - 2
Ix.NET/Source/System.Interactive.Async/First.cs

@@ -94,7 +94,9 @@ namespace System.Linq
                 return list[0];
             }
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (await e.MoveNextAsync(cancellationToken)
                            .ConfigureAwait(false))
@@ -102,6 +104,11 @@ namespace System.Linq
                     return e.Current;
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
             throw new InvalidOperationException(Strings.NO_ELEMENTS);
         }
 
@@ -113,7 +120,9 @@ namespace System.Linq
                 return list[0];
             }
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (await e.MoveNextAsync(cancellationToken)
                            .ConfigureAwait(false))
@@ -121,6 +130,11 @@ namespace System.Linq
                     return e.Current;
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
             return default(TSource);
         }
     }

+ 8 - 1
Ix.NET/Source/System.Interactive.Async/ForEach.cs

@@ -98,7 +98,10 @@ namespace System.Linq
         private static async Task ForEachAsync_<TSource>(IAsyncEnumerable<TSource> source, Action<TSource, int> action, CancellationToken cancellationToken)
         {
             var index = 0;
-            using (var e = source.GetAsyncEnumerator())
+
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -106,6 +109,10 @@ namespace System.Linq
                     action(e.Current, checked(index++));
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
     }
 }

+ 7 - 6
Ix.NET/Source/System.Interactive.Async/Generate.cs

@@ -51,14 +51,14 @@ namespace System.Linq
                 return new GenerateAsyncIterator<TState, TResult>(initialState, condition, iterate, resultSelector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 currentState = default(TState);
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
-            protected override Task<bool> MoveNextCore()
+            protected override async Task<bool> MoveNextCore()
             {
                 switch (state)
                 {
@@ -80,13 +80,14 @@ namespace System.Linq
                         if (condition(currentState))
                         {
                             current = resultSelector(currentState);
-                            return TaskExt.True;
+                            return true;
                         }
                         break;
                 }
 
-                Dispose();
-                return TaskExt.False;
+                await DisposeAsync().ConfigureAwait(false);
+
+                return false;
             }
         }
     }

+ 1 - 4
Ix.NET/Source/System.Interactive.Async/GroupJoin.cs

@@ -133,10 +133,7 @@ namespace System.Linq
 
                 public TResult Current { get; private set; }
 
-                public void Dispose()
-                {
-                    _outer.Dispose();
-                }
+                public Task DisposeAsync() => _outer.DisposeAsync();
             }
         }
     }

+ 9 - 9
Ix.NET/Source/System.Interactive.Async/Grouping.cs

@@ -147,7 +147,7 @@ namespace System.Linq
                 return new GroupedResultAsyncEnumerable<TSource, TKey, TResult>(source, keySelector, resultSelector, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
@@ -156,7 +156,7 @@ namespace System.Linq
                     lookup = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -176,7 +176,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
@@ -236,7 +236,7 @@ namespace System.Linq
                 return new GroupedAsyncEnumerable<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
@@ -245,7 +245,7 @@ namespace System.Linq
                     lookup = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -265,7 +265,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
@@ -321,7 +321,7 @@ namespace System.Linq
             {
                 return new GroupedAsyncEnumerable<TSource, TKey>(source, keySelector, comparer);
             }
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
@@ -330,7 +330,7 @@ namespace System.Linq
                     lookup = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -350,7 +350,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 1 - 1
Ix.NET/Source/System.Interactive.Async/IAsyncEnumerator.cs

@@ -11,7 +11,7 @@ namespace System.Collections.Generic
     ///     retrieved asynchronously.
     /// </summary>
     /// <typeparam name="T">Element type.</typeparam>
-    public interface IAsyncEnumerator<out T> : IDisposable
+    public interface IAsyncEnumerator<out T> : IAsyncDisposable
     {
         /// <summary>
         ///     Gets the current element in the iteration.

+ 4 - 4
Ix.NET/Source/System.Interactive.Async/IgnoreElements.cs

@@ -36,15 +36,15 @@ namespace System.Linq
                 return new IgnoreElementsAsyncIterator<TSource>(source);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -66,7 +66,7 @@ namespace System.Linq
                         break; // case
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 4 - 4
Ix.NET/Source/System.Interactive.Async/Intersect.cs

@@ -63,17 +63,17 @@ namespace System.Linq
                 return new IntersectAsyncIterator<TSource>(first, second, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (firstEnumerator != null)
                 {
-                    firstEnumerator.Dispose();
+                    await firstEnumerator.DisposeAsync().ConfigureAwait(false);
                     firstEnumerator = null;
                 }
 
                 set = null;
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -120,7 +120,7 @@ namespace System.Linq
                             }
                         } while (moveNext);
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 4 - 4
Ix.NET/Source/System.Interactive.Async/Join.cs

@@ -78,15 +78,15 @@ namespace System.Linq
                 return new JoinAsyncIterator<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (outerEnumerator != null)
                 {
-                    outerEnumerator.Dispose();
+                    await outerEnumerator.DisposeAsync().ConfigureAwait(false);
                     outerEnumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             // State machine vars
@@ -165,7 +165,7 @@ namespace System.Linq
                                 break;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
 
                         break;
                 }

+ 16 - 2
Ix.NET/Source/System.Interactive.Async/Last.cs

@@ -100,7 +100,9 @@ namespace System.Linq
                 }
             }
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -109,6 +111,11 @@ namespace System.Linq
                     last = e.Current;
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
             if (!hasLast)
                 throw new InvalidOperationException(Strings.NO_ELEMENTS);
             return last;
@@ -128,7 +135,9 @@ namespace System.Linq
                 }
             }
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await e.MoveNextAsync(cancellationToken)
                               .ConfigureAwait(false))
@@ -137,6 +146,11 @@ namespace System.Linq
                     last = e.Current;
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
             return !hasLast ? default(TSource) : last;
         }
     }

+ 24 - 3
Ix.NET/Source/System.Interactive.Async/Lookup.cs

@@ -196,7 +196,10 @@ namespace System.Linq.Internal
             Debug.Assert(elementSelector != null);
 
             var lookup = new Lookup<TKey, TElement>(comparer);
-            using (var enu = source.GetAsyncEnumerator())
+
+            var enu = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await enu.MoveNextAsync(cancellationToken)
                                 .ConfigureAwait(false))
@@ -205,6 +208,10 @@ namespace System.Linq.Internal
                           .Add(elementSelector(enu.Current));
                 }
             }
+            finally
+            {
+                await enu.DisposeAsync().ConfigureAwait(false);
+            }
 
             return lookup;
         }
@@ -215,7 +222,10 @@ namespace System.Linq.Internal
             Debug.Assert(keySelector != null);
 
             var lookup = new Lookup<TKey, TElement>(comparer);
-            using (var enu = source.GetAsyncEnumerator())
+
+            var enu = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await enu.MoveNextAsync(cancellationToken)
                                 .ConfigureAwait(false))
@@ -224,6 +234,10 @@ namespace System.Linq.Internal
                           .Add(enu.Current);
                 }
             }
+            finally
+            {
+                await enu.DisposeAsync().ConfigureAwait(false);
+            }
 
             return lookup;
         }
@@ -231,7 +245,10 @@ namespace System.Linq.Internal
         internal static async Task<Lookup<TKey, TElement>> CreateForJoinAsync(IAsyncEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
         {
             var lookup = new Lookup<TKey, TElement>(comparer);
-            using (var enu = source.GetAsyncEnumerator())
+
+            var enu = source.GetAsyncEnumerator();
+
+            try
             {
                 while (await enu.MoveNextAsync()
                                 .ConfigureAwait(false))
@@ -244,6 +261,10 @@ namespace System.Linq.Internal
                     }
                 }
             }
+            finally
+            {
+                await enu.DisposeAsync().ConfigureAwait(false);
+            }
 
             return lookup;
         }

+ 7 - 1
Ix.NET/Source/System.Interactive.Async/Min.cs

@@ -493,7 +493,9 @@ namespace System.Linq
         {
             var result = new List<TSource>();
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (!await e.MoveNextAsync()
                             .ConfigureAwait(false))
@@ -524,6 +526,10 @@ namespace System.Linq
                     }
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
 
             return result;
         }

+ 6 - 6
Ix.NET/Source/System.Interactive.Async/OnErrorResumeNext.cs

@@ -63,7 +63,7 @@ namespace System.Linq
                 return new OnErrorResumeNextAsyncIterator<TSource>(sources);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (sourcesEnumerator != null)
                 {
@@ -73,11 +73,11 @@ namespace System.Linq
 
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -118,15 +118,15 @@ namespace System.Linq
                             }
 
                             // Done with the current one, go to the next
-                            enumerator.Dispose();
+                            await enumerator.DisposeAsync().ConfigureAwait(false);
                             enumerator = null;
                         }
 
                         break; // case
                         
                 }
-                
-                Dispose();
+
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 4 - 4
Ix.NET/Source/System.Interactive.Async/OrderedAsyncEnumerable.cs

@@ -51,7 +51,7 @@ namespace System.Linq
         }
 
 
-        public override void Dispose()
+        public override async Task DisposeAsync()
         {
             if (enumerator != null)
             {
@@ -61,10 +61,10 @@ namespace System.Linq
 
             if (parentEnumerator != null)
             {
-                parentEnumerator.Dispose();
+                await parentEnumerator.DisposeAsync().ConfigureAwait(false);
                 parentEnumerator = null;
             }
-            base.Dispose();
+            await base.DisposeAsync().ConfigureAwait(false);
         }
 
         protected override async Task<bool> MoveNextCore()
@@ -87,7 +87,7 @@ namespace System.Linq
                         return true;
                     }
 
-                    Dispose();
+                    await DisposeAsync().ConfigureAwait(false);
                     break;
             }
 

+ 5 - 5
Ix.NET/Source/System.Interactive.Async/Repeat.cs

@@ -88,15 +88,15 @@ namespace System.Linq
                 return new RepeatSequenceAsyncIterator<TSource>(source, count);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -107,7 +107,7 @@ namespace System.Linq
 
                         if (enumerator != null)
                         {
-                            enumerator.Dispose();
+                            await enumerator.DisposeAsync().ConfigureAwait(false);
                             enumerator = null;
                         }
 
@@ -130,7 +130,7 @@ namespace System.Linq
 
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
 
                 return false;
             }

+ 3 - 3
Ix.NET/Source/System.Interactive.Async/Reverse.cs

@@ -83,10 +83,10 @@ namespace System.Linq
                 return new ReverseAsyncIterator<TSource>(source);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 items = null; // Just in case this ends up being long-lived, allow the memory to be reclaimed.
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
 
@@ -113,7 +113,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 8 - 8
Ix.NET/Source/System.Interactive.Async/Scan.cs

@@ -55,16 +55,16 @@ namespace System.Linq
                 return new ScanAsyncEnumerable<TSource, TAccumulate>(source, seed, accumulator);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                     accumulated = default(TAccumulate);
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -92,7 +92,7 @@ namespace System.Linq
                         
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -121,16 +121,16 @@ namespace System.Linq
                 return new ScanAsyncEnumerable<TSource>(source, accumulator);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                     accumulated = default(TSource);
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -167,7 +167,7 @@ namespace System.Linq
 
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 14 - 14
Ix.NET/Source/System.Interactive.Async/Select.cs

@@ -67,15 +67,15 @@ namespace System.Linq
                 return new SelectEnumerableAsyncIterator<TSource, TResult>(source, selector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             public override IAsyncEnumerable<TResult1> Select<TResult1>(Func<TResult, TResult1> selector)
@@ -100,7 +100,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
@@ -129,15 +129,15 @@ namespace System.Linq
                 return new SelectEnumerableWithIndexAsyncIterator<TSource, TResult>(source, selector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -162,7 +162,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
@@ -190,7 +190,7 @@ namespace System.Linq
                 return new SelectIListIterator<TSource, TResult>(source, selector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
@@ -198,7 +198,7 @@ namespace System.Linq
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             public override IAsyncEnumerable<TResult1> Select<TResult1>(Func<TResult, TResult1> selector)
@@ -206,7 +206,7 @@ namespace System.Linq
                 return new SelectIListIterator<TSource, TResult1>(source, CombineSelectors(this.selector, selector));
             }
 
-            protected override Task<bool> MoveNextCore()
+            protected override async Task<bool> MoveNextCore()
             {
                 switch (state)
                 {
@@ -219,14 +219,14 @@ namespace System.Linq
                         if (enumerator.MoveNext())
                         {
                             current = selector(enumerator.Current);
-                            return Task.FromResult(true);
+                            return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
-                return Task.FromResult(false);
+                return false;
             }
         }
     }

+ 40 - 24
Ix.NET/Source/System.Interactive.Async/SelectMany.cs

@@ -92,21 +92,21 @@ namespace System.Linq
                 return new SelectManyAsyncIterator<TSource, TResult>(source, selector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (sourceEnumerator != null)
                 {
-                    sourceEnumerator.Dispose();
+                    await sourceEnumerator.DisposeAsync().ConfigureAwait(false);
                     sourceEnumerator = null;
                 }
 
                 if (resultEnumerator != null)
                 {
-                    resultEnumerator.Dispose();
+                    await resultEnumerator.DisposeAsync().ConfigureAwait(false);
                     resultEnumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -126,7 +126,11 @@ namespace System.Linq
                                 if (await sourceEnumerator.MoveNextAsync()
                                                           .ConfigureAwait(false))
                                 {
-                                    resultEnumerator?.Dispose();
+                                    if (resultEnumerator != null)
+                                    {
+                                        await resultEnumerator.DisposeAsync().ConfigureAwait(false);
+                                    }
+
                                     resultEnumerator = selector(sourceEnumerator.Current)
                                         .GetAsyncEnumerator();
 
@@ -150,7 +154,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -185,23 +189,23 @@ namespace System.Linq
                 return new SelectManyAsyncIterator<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (sourceEnumerator != null)
                 {
-                    sourceEnumerator.Dispose();
+                    await sourceEnumerator.DisposeAsync().ConfigureAwait(false);
                     sourceEnumerator = null;
                 }
 
                 if (resultEnumerator != null)
                 {
-                    resultEnumerator.Dispose();
+                    await resultEnumerator.DisposeAsync().ConfigureAwait(false);
                     resultEnumerator = null;
                 }
 
                 currentSource = default(TSource);
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -221,7 +225,11 @@ namespace System.Linq
                                 if (await sourceEnumerator.MoveNextAsync()
                                                           .ConfigureAwait(false))
                                 {
-                                    resultEnumerator?.Dispose();
+                                    if (resultEnumerator != null)
+                                    {
+                                        await resultEnumerator.DisposeAsync().ConfigureAwait(false);
+                                    }
+
                                     currentSource = sourceEnumerator.Current;
                                     resultEnumerator = collectionSelector(currentSource)
                                         .GetAsyncEnumerator();
@@ -246,7 +254,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -282,23 +290,23 @@ namespace System.Linq
                 return new SelectManyWithIndexAsyncIterator<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (sourceEnumerator != null)
                 {
-                    sourceEnumerator.Dispose();
+                    await sourceEnumerator.DisposeAsync().ConfigureAwait(false);
                     sourceEnumerator = null;
                 }
 
                 if (resultEnumerator != null)
                 {
-                    resultEnumerator.Dispose();
+                    await resultEnumerator.DisposeAsync().ConfigureAwait(false);
                     resultEnumerator = null;
                 }
 
                 currentSource = default(TSource);
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -319,7 +327,11 @@ namespace System.Linq
                                 if (await sourceEnumerator.MoveNextAsync()
                                                           .ConfigureAwait(false))
                                 {
-                                    resultEnumerator?.Dispose();
+                                    if (resultEnumerator != null)
+                                    {
+                                        await resultEnumerator.DisposeAsync().ConfigureAwait(false);
+                                    }
+
                                     currentSource = sourceEnumerator.Current;
 
                                     checked
@@ -350,7 +362,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -382,21 +394,21 @@ namespace System.Linq
                 return new SelectManyWithIndexAsyncIterator<TSource, TResult>(source, selector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (sourceEnumerator != null)
                 {
-                    sourceEnumerator.Dispose();
+                    await sourceEnumerator.DisposeAsync().ConfigureAwait(false);
                     sourceEnumerator = null;
                 }
 
                 if (resultEnumerator != null)
                 {
-                    resultEnumerator.Dispose();
+                    await resultEnumerator.DisposeAsync().ConfigureAwait(false);
                     resultEnumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -417,7 +429,11 @@ namespace System.Linq
                                 if (await sourceEnumerator.MoveNextAsync()
                                                           .ConfigureAwait(false))
                                 {
-                                    resultEnumerator?.Dispose();
+                                    if (resultEnumerator != null)
+                                    {
+                                        await resultEnumerator.DisposeAsync().ConfigureAwait(false);
+                                    }
+
                                     checked
                                     {
                                         index++;
@@ -445,7 +461,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 24 - 10
Ix.NET/Source/System.Interactive.Async/SequenceEqual.cs

@@ -68,21 +68,35 @@ namespace System.Linq
                 }
             }
 
-            using (var e1 = first.GetAsyncEnumerator())
-            using (var e2 = second.GetAsyncEnumerator())
+            var e1 = first.GetAsyncEnumerator();
+
+            try
             {
-                while (await e1.MoveNextAsync()
-                               .ConfigureAwait(false))
+                var e2 = second.GetAsyncEnumerator();
+
+                try
                 {
-                    if (!(await e2.MoveNextAsync()
-                                  .ConfigureAwait(false) && comparer.Equals(e1.Current, e2.Current)))
+                    while (await e1.MoveNextAsync()
+                                   .ConfigureAwait(false))
                     {
-                        return false;
+                        if (!(await e2.MoveNextAsync()
+                                      .ConfigureAwait(false) && comparer.Equals(e1.Current, e2.Current)))
+                        {
+                            return false;
+                        }
                     }
-                }
 
-                return !await e2.MoveNextAsync()
-                                .ConfigureAwait(false);
+                    return !await e2.MoveNextAsync()
+                                    .ConfigureAwait(false);
+                }
+                finally
+                {
+                    await e2.DisposeAsync().ConfigureAwait(false);
+                }
+            }
+            finally
+            {
+                await e1.DisposeAsync().ConfigureAwait(false);
             }
         }
     }

+ 15 - 2
Ix.NET/Source/System.Interactive.Async/Single.cs

@@ -99,7 +99,9 @@ namespace System.Linq
                 throw new InvalidOperationException(Strings.MORE_THAN_ONE_ELEMENT);
             }
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (!await e.MoveNextAsync(cancellationToken)
                             .ConfigureAwait(false))
@@ -114,6 +116,10 @@ namespace System.Linq
                 }
                 return result;
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
 
         private static async Task<TSource> SingleOrDefault_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
@@ -128,7 +134,9 @@ namespace System.Linq
                 throw new InvalidOperationException(Strings.MORE_THAN_ONE_ELEMENT);
             }
 
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 if (!await e.MoveNextAsync(cancellationToken)
                             .ConfigureAwait(false))
@@ -143,6 +151,11 @@ namespace System.Linq
                     return result;
                 }
             }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
             throw new InvalidOperationException(Strings.MORE_THAN_ONE_ELEMENT);
         }
     }

+ 16 - 16
Ix.NET/Source/System.Interactive.Async/Skip.cs

@@ -93,15 +93,15 @@ namespace System.Linq
                 return new SkipAsyncIterator<TSource>(source, count);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
 
@@ -136,7 +136,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -162,16 +162,16 @@ namespace System.Linq
                 return new SkipLastAsyncIterator<TSource>(source, count);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
                 queue = null; // release the memory
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
 
@@ -203,7 +203,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -230,15 +230,15 @@ namespace System.Linq
                 return new SkipWhileAsyncIterator<TSource>(source, predicate);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -279,7 +279,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -307,15 +307,15 @@ namespace System.Linq
                 return new SkipWhileWithIndexAsyncIterator<TSource>(source, predicate);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -362,7 +362,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 17 - 17
Ix.NET/Source/System.Interactive.Async/Take.cs

@@ -79,15 +79,15 @@ namespace System.Linq
                 return new TakeAsyncIterator<TSource>(source, count);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
 
@@ -113,7 +113,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -140,16 +140,16 @@ namespace System.Linq
                 return new TakeLastAsyncIterator<TSource>(source, count);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
                 queue = null; // release the memory
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
 
@@ -188,7 +188,7 @@ namespace System.Linq
                                 {
                                     isDone = true;
                                     // Dispose early here as we can
-                                    enumerator.Dispose();
+                                    await enumerator.DisposeAsync().ConfigureAwait(false);
                                     enumerator = null;
                                 }
 
@@ -207,7 +207,7 @@ namespace System.Linq
                         break; // case
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -233,15 +233,15 @@ namespace System.Linq
                 return new TakeWhileAsyncIterator<TSource>(source, predicate);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -271,7 +271,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }
@@ -298,15 +298,15 @@ namespace System.Linq
                 return new TakeWhileWithIndexAsyncIterator<TSource>(source, predicate);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -341,7 +341,7 @@ namespace System.Linq
                         break;
                 }
 
-                Dispose();
+                await DisposeAsync().ConfigureAwait(false);
                 return false;
             }
         }

+ 27 - 21
Ix.NET/Source/System.Interactive.Async/ToAsyncEnumerable.cs

@@ -49,7 +49,7 @@ namespace System.Linq
                             return false;
                         },
                         () => value,
-                        () => { });
+                        () => TaskExt.True);
                 });
         }
 
@@ -63,7 +63,9 @@ namespace System.Linq
 
         private static IEnumerable<TSource> ToEnumerable_<TSource>(IAsyncEnumerable<TSource> source)
         {
-            using (var e = source.GetAsyncEnumerator())
+            var e = source.GetAsyncEnumerator();
+
+            try
             {
                 while (true)
                 {
@@ -74,6 +76,10 @@ namespace System.Linq
                     yield return c;
                 }
             }
+            finally
+            {
+                e.DisposeAsync().Wait();
+            }
         }
 
         internal sealed class AsyncEnumerableAdapter<T> : AsyncIterator<T>, IIListProvider<T>
@@ -94,7 +100,7 @@ namespace System.Linq
                 return new AsyncEnumerableAdapter<T>(source);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
@@ -102,10 +108,10 @@ namespace System.Linq
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
-            protected override Task<bool> MoveNextCore()
+            protected override async Task<bool> MoveNextCore()
             {
                 switch (state)
                 {
@@ -118,14 +124,14 @@ namespace System.Linq
                         if (enumerator.MoveNext())
                         {
                             current = enumerator.Current;
-                            return Task.FromResult(true);
+                            return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
-                
-                return Task.FromResult(false);
+
+                return false;
             }
 
             // These optimizations rely on the Sys.Linq impls from IEnumerable to optimize
@@ -163,7 +169,7 @@ namespace System.Linq
                 return new AsyncIListEnumerableAdapter<T>(source);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
@@ -171,10 +177,10 @@ namespace System.Linq
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
-            protected override Task<bool> MoveNextCore()
+            protected override async Task<bool> MoveNextCore()
             {
                 switch (state)
                 {
@@ -187,14 +193,14 @@ namespace System.Linq
                         if (enumerator.MoveNext())
                         {
                             current = enumerator.Current;
-                            return Task.FromResult(true);
+                            return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
-                return Task.FromResult(false);
+                return false;
             }
 
             public override IAsyncEnumerable<TResult> Select<TResult>(Func<T, TResult> selector)
@@ -266,17 +272,17 @@ namespace System.Linq
                 return new AsyncICollectionEnumerableAdapter<T>(source);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
                     enumerator.Dispose();
                     enumerator = null;
                 }
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
-            protected override Task<bool> MoveNextCore()
+            protected override async Task<bool> MoveNextCore()
             {
                 switch (state)
                 {
@@ -288,12 +294,12 @@ namespace System.Linq
                         if (enumerator.MoveNext())
                         {
                             current = enumerator.Current;
-                            return Task.FromResult(true);
+                            return true;
                         }
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
-                return Task.FromResult(false);
+                return false;
             }
 
             // These optimizations rely on the Sys.Linq impls from IEnumerable to optimize

+ 6 - 5
Ix.NET/Source/System.Interactive.Async/ToObservable.cs

@@ -71,6 +71,7 @@ namespace System.Linq
                         {
                             subscription.Dispose();
                             // Should we cancel in-flight operations somehow?
+                            return TaskExt.True;
                         });
                 });
         }
@@ -186,16 +187,16 @@ namespace System.Linq
 
                 var f = default(Action);
                 f = () => e.MoveNextAsync()
-                           .ContinueWith(t =>
+                           .ContinueWith(async t =>
                                          {
                                              if (t.IsFaulted)
                                              {
                                                  observer.OnError(t.Exception);
-                                                 e.Dispose();
+                                                 await e.DisposeAsync().ConfigureAwait(false);
                                              }
                                              else if (t.IsCanceled)
                                              {
-                                                 e.Dispose();
+                                                 await e.DisposeAsync().ConfigureAwait(false);
                                              }
                                              else if (t.IsCompleted)
                                              {
@@ -213,14 +214,14 @@ namespace System.Linq
                                                  else
                                                  {
                                                      observer.OnCompleted();
-                                                     e.Dispose();
+                                                     await e.DisposeAsync().ConfigureAwait(false);
                                                  }
                                              }
                                          }, ctd.Token);
 
                 f();
 
-                return Disposable.Create(ctd, e);
+                return Disposable.Create(ctd, Disposable.Create(() => { e.DisposeAsync(); /* REVIEW: fire-and-forget? */ }));
             }
         }
     }

+ 4 - 4
Ix.NET/Source/System.Interactive.Async/Using.cs

@@ -44,11 +44,11 @@ namespace System.Linq
                 return new UsingAsyncIterator<TSource, TResource>(resourceFactory, enumerableFactory);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
@@ -58,7 +58,7 @@ namespace System.Linq
                     resource = default(TResource);
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -78,7 +78,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 12 - 12
Ix.NET/Source/System.Interactive.Async/Where.cs

@@ -63,14 +63,14 @@ namespace System.Linq
                 return new WhereEnumerableAsyncIterator<TSource>(source, predicate);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             public override IAsyncEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector)
@@ -104,7 +104,7 @@ namespace System.Linq
                             }
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
@@ -134,14 +134,14 @@ namespace System.Linq
                 return new WhereEnumerableWithIndexAsyncIterator<TSource>(source, predicate);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -170,7 +170,7 @@ namespace System.Linq
                             }
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 
@@ -202,15 +202,15 @@ namespace System.Linq
                 return new WhereSelectEnumerableAsyncIterator<TSource, TResult>(source, predicate, selector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (enumerator != null)
                 {
-                    enumerator.Dispose();
+                    await enumerator.DisposeAsync().ConfigureAwait(false);
                     enumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             public override IAsyncEnumerable<TResult1> Select<TResult1>(Func<TResult, TResult1> selector)
@@ -239,7 +239,7 @@ namespace System.Linq
                             }
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 5 - 5
Ix.NET/Source/System.Interactive.Async/Zip.cs

@@ -48,20 +48,20 @@ namespace System.Linq
                 return new ZipAsyncIterator<TFirst, TSecond, TResult>(first, second, selector);
             }
 
-            public override void Dispose()
+            public override async Task DisposeAsync()
             {
                 if (firstEnumerator != null)
                 {
-                    firstEnumerator.Dispose();
+                    await firstEnumerator.DisposeAsync().ConfigureAwait(false);
                     firstEnumerator = null;
                 }
                 if (secondEnumerator != null)
                 {
-                    secondEnumerator.Dispose();
+                    await secondEnumerator.DisposeAsync().ConfigureAwait(false);
                     secondEnumerator = null;
                 }
 
-                base.Dispose();
+                await base.DisposeAsync().ConfigureAwait(false);
             }
 
             protected override async Task<bool> MoveNextCore()
@@ -89,7 +89,7 @@ namespace System.Linq
                             return true;
                         }
 
-                        Dispose();
+                        await DisposeAsync().ConfigureAwait(false);
                         break;
                 }
 

+ 4 - 3
Ix.NET/Source/Tests/AsyncTests.Bugs.cs

@@ -114,7 +114,7 @@ namespace Tests
 
             // We have to call move next because otherwise the internal enumerator is never allocated
             await e.MoveNextAsync();
-            e.Dispose();
+            await e.DisposeAsync();
 
             await disposed.Task;
 
@@ -212,9 +212,10 @@ namespace Tests
                     _disposeCounter = disposeCounter;
                 }
 
-                public void Dispose()
+                public Task DisposeAsync()
                 {
                     _disposeCounter.DisposeCount++;
+                    return Task.FromResult(true);
                 }
 
                 public Task<bool> MoveNextAsync()
@@ -243,7 +244,7 @@ namespace Tests
             return AsyncEnumerable.CreateEnumerable<T>(() =>
             {
                 var e = source.GetAsyncEnumerator();
-                return AsyncEnumerable.CreateEnumerator<T>(e.MoveNextAsync, () => e.Current, () => { e.Dispose(); a(); });
+                return AsyncEnumerable.CreateEnumerator<T>(e.MoveNextAsync, () => e.Current, async () => { await e.DisposeAsync(); a(); });
             });
         }
 

+ 3 - 3
Ix.NET/Source/Tests/AsyncTests.Conversions.cs

@@ -453,7 +453,7 @@ namespace Tests
                 () => AsyncEnumerable.CreateEnumerator<int>(
                     () => Task.FromResult(false),
                     () => { throw new InvalidOperationException(); },
-                    () => { evt.Set(); }));
+                    () => { evt.Set(); return Task.FromResult(true); }));
 
             ae
                 .ToObservable()
@@ -491,7 +491,7 @@ namespace Tests
                         return true;
                     },
                     () => 1,
-                    () => { evt.Set(); }));
+                    () => { evt.Set(); return Task.FromResult(true); }));
 
             subscription = ae
                 .ToObservable()
@@ -535,7 +535,7 @@ namespace Tests
                         return true;
                     },
                     () => 1,
-                    () => { evt.Set(); }));
+                    () => { evt.Set(); return Task.FromResult(true); }));
 
             subscription = ae
                 .ToObservable()

+ 10 - 10
Ix.NET/Source/Tests/AsyncTests.Creation.cs

@@ -19,7 +19,7 @@ namespace Tests
         public void Create_Null()
         {
             AssertThrows<ArgumentNullException>(() => AsyncEnumerable.CreateEnumerable<int>(null));
-            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.CreateEnumerator<int>(null, () => 3, () => {}));
+            AssertThrows<ArgumentNullException>(() => AsyncEnumerable.CreateEnumerator<int>(null, () => 3, () => Task.FromResult(true)));
        
         }
 
@@ -27,7 +27,7 @@ namespace Tests
         public void Create_Iterator_Throws()
         {
      
-           var iter = AsyncEnumerable.CreateEnumerator<int>(() => Task.FromResult(true), () => 3, () => { });
+           var iter = AsyncEnumerable.CreateEnumerator<int>(() => Task.FromResult(true), () => 3, () => Task.FromResult(true));
 
             var enu = (IAsyncEnumerable<int>)iter;
 
@@ -43,14 +43,14 @@ namespace Tests
         }
 
         [Fact]
-        public void Never()
+        public async Task Never()
         {
             var xs = AsyncEnumerable.Never<int>();
 
             var e = xs.GetAsyncEnumerator();
             Assert.False(e.MoveNextAsync().IsCompleted); // Very rudimentary check
             AssertThrows<InvalidOperationException>(() => Nop(e.Current));
-            e.Dispose();
+            await e.DisposeAsync();
         }
 
         [Fact]
@@ -157,7 +157,7 @@ namespace Tests
         }
 
         [Fact]
-        public void Repeat3()
+        public async Task Repeat3()
         {
             var xs = AsyncEnumerable.Repeat(2);
 
@@ -167,7 +167,7 @@ namespace Tests
             HasNext(e, 2);
             HasNext(e, 2);
             HasNext(e, 2);
-            e.Dispose();
+            await e.DisposeAsync();
         }
 
         [Fact]
@@ -213,7 +213,7 @@ namespace Tests
         }
 
         [Fact]
-        public void Generate1()
+        public async Task Generate1()
         {
             var xs = AsyncEnumerable.Generate(0, x => x < 5, x => x + 1, x => x * x);
 
@@ -224,7 +224,7 @@ namespace Tests
             HasNext(e, 9);
             HasNext(e, 16);
             NoNext(e);
-            e.Dispose();
+            await e.DisposeAsync();
         }
 
         [Fact]
@@ -296,7 +296,7 @@ namespace Tests
         }
 
         [Fact]
-        public void Using2()
+        public async Task Using2()
         {
             var i = 0;
             var d = 0;
@@ -315,7 +315,7 @@ namespace Tests
             var e = xs.GetAsyncEnumerator();
             Assert.Equal(1, i);
 
-            e.Dispose();
+            await e.DisposeAsync();
             Assert.Equal(1, d);
         }
 

+ 2 - 2
Ix.NET/Source/Tests/AsyncTests.Exceptions.cs

@@ -377,7 +377,7 @@ namespace Tests
         }
 
         [Fact]
-        public void Finally5()
+        public async Task Finally5()
         {
             var b = false;
 
@@ -388,7 +388,7 @@ namespace Tests
             Assert.False(b);
             HasNext(e, 1);
 
-            e.Dispose();
+            await e.DisposeAsync();
 
             Assert.True(b);
         }

+ 10 - 10
Ix.NET/Source/Tests/AsyncTests.Single.cs

@@ -2299,7 +2299,7 @@ namespace Tests
         }
 
         [Fact]
-        public void GroupBy16()
+        public async Task GroupBy16()
         {
             var xs = AsyncEnumerable.Range(0, 10);
             var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
@@ -2315,7 +2315,7 @@ namespace Tests
             HasNext(g1e, 'g');
             HasNext(g1e, 'j');
             NoNext(g1e);
-            g1e.Dispose();
+            await g1e.DisposeAsync();
 
             Assert.True(e.MoveNextAsync().Result);
             var g2 = e.Current;
@@ -2325,7 +2325,7 @@ namespace Tests
             HasNext(g2e, 'e');
             HasNext(g2e, 'h');
             NoNext(g2e);
-            g2e.Dispose();
+            await g2e.DisposeAsync();
 
             Assert.True(e.MoveNextAsync().Result);
             var g3 = e.Current;
@@ -2335,27 +2335,27 @@ namespace Tests
             HasNext(g3e, 'f');
             HasNext(g3e, 'i');
             NoNext(g3e);
-            g3e.Dispose();
+            await g3e.DisposeAsync();
 
             NoNext(e);
 
-            e.Dispose();
+            await e.DisposeAsync();
         }
 
         [Fact]
-        public void GroupBy17()
+        public async Task GroupBy17()
         {
             var xs = AsyncEnumerable.Range(0, 10);
             var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
 
             var e = ys.GetAsyncEnumerator();
-            e.Dispose();
+            await e.DisposeAsync();
 
             Assert.False(e.MoveNextAsync().Result);
         }
 
         [Fact]
-        public void GroupBy18()
+        public async Task GroupBy18()
         {
             var xs = AsyncEnumerable.Range(0, 10);
             var ys = xs.GroupBy(x => x, x => (char)('a' + x), new EqMod(3));
@@ -2368,13 +2368,13 @@ namespace Tests
             var g1e = g1.GetAsyncEnumerator();
             HasNext(g1e, 'a');
 
-            e.Dispose();
+            await e.DisposeAsync();
 
             HasNext(g1e, 'd');
             HasNext(g1e, 'g');
             HasNext(g1e, 'j');
             NoNext(g1e);
-            g1e.Dispose();
+            await g1e.DisposeAsync();
 
             Assert.False(e.MoveNextAsync().Result);
         }

+ 2 - 2
Ix.NET/Source/Tests/AsyncTests.cs

@@ -67,8 +67,8 @@ namespace Tests
 
             Assert.Equal(en1.GetType(), en2.GetType());
 
-            en1.Dispose();
-            en2.Dispose();
+            await en1.DisposeAsync();
+            await en2.DisposeAsync();
 
             var e1t = enumerable.ToList();
             var e2t = enumerable.ToList();