Browse Source

Disposing EventLoopScheduler with in-flight items (closes #286)

Eugene Baranov 6 years ago
parent
commit
fa3cdc6af2

+ 10 - 2
Rx.NET/Source/src/System.Reactive/Concurrency/EventLoopScheduler.cs

@@ -153,7 +153,7 @@ namespace System.Reactive.Concurrency
             {
                 if (_disposed)
                 {
-                    throw new ObjectDisposedException("");
+                    throw new ObjectDisposedException(nameof(EventLoopScheduler));
                 }
 
                 if (dueTime <= TimeSpan.Zero)
@@ -351,7 +351,15 @@ namespace System.Reactive.Concurrency
                     {
                         if (!item.IsCanceled)
                         {
-                            item.Invoke();
+                            try
+                            {
+                                item.Invoke();
+                            }
+                            catch (ObjectDisposedException ex) when (nameof(EventLoopScheduler).Equals(ex.ObjectName))
+                            {
+                                // Since we are not inside the lock at this point
+                                // the scheduler can be disposed before the item had a chance to run
+                            }
                         }
                     }
                 }

+ 14 - 0
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/EventLoopSchedulerTest.cs

@@ -7,6 +7,7 @@ using System.Collections.Generic;
 using System.Diagnostics;
 using System.Reactive.Concurrency;
 using System.Reactive.Disposables;
+using System.Reactive.Linq;
 using System.Threading;
 using Microsoft.Reactive.Testing;
 using Xunit;
@@ -41,6 +42,19 @@ namespace ReactiveTests.Tests
             Assert.True(res.Seconds < 1);
         }
 
+        [Fact]
+        public void EventLoop_DisposeWithInFlightActions()
+        {
+            using (var scheduler = new EventLoopScheduler())
+            using (var subscription = Observable
+                .Range(1, 10)
+                .ObserveOn(scheduler)
+                .Subscribe(_ => Thread.Sleep(50)))
+            {
+                Thread.Sleep(50);
+            }
+        }
+
         [Fact]
         public void EventLoop_ScheduleAction()
         {