浏览代码

In AsyncIterator.Dispose, check whether cancellationTokenSource is null. Since AsyncIterator is not public, the problem here only arises when a reference of AsyncIterator is explicitly cast to IDisposable and disposed of - in IoC-containers like Autofac, this is a common scenario since it keeps track of all created disposables so this is gonna explode somewhere without this fix.

Daniel Weber 9 年之前
父节点
当前提交
c1b2e10858
共有 2 个文件被更改,包括 13 次插入3 次删除
  1. 6 3
      Ix.NET/Source/System.Interactive.Async/AsyncIterator.cs
  2. 7 0
      Ix.NET/Source/Tests/AsyncTests.Bugs.cs

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

@@ -48,11 +48,14 @@ namespace System.Linq
 
             public virtual void Dispose()
             {
-                if (!cancellationTokenSource.IsCancellationRequested)
+                if (cancellationTokenSource != null)
                 {
-                    cancellationTokenSource.Cancel();
+                    if (!cancellationTokenSource.IsCancellationRequested)
+                    {
+                        cancellationTokenSource.Cancel();
+                    }
+                    cancellationTokenSource.Dispose();
                 }
-                cancellationTokenSource.Dispose();
 
                 current = default(TSource);
                 state = AsyncIteratorState.Disposed;

+ 7 - 0
Ix.NET/Source/Tests/AsyncTests.Bugs.cs

@@ -377,6 +377,13 @@ namespace Tests
             Assert.True(disposes.All(d => d.DisposeCount == 1));
         }
 
+        [Fact]
+        public void DisposeAfterCreation()
+        {
+            var enumerable = AsyncEnumerable.Return(0) as IDisposable;
+            enumerable?.Dispose();
+        }
+
         private class DisposeCounter : IAsyncEnumerable<object>
         {
             public int DisposeCount { get; private set; }