Browse Source

Implement optional swallowing of post-unsubscribe exceptions from tasks

Ian Griffiths 2 years ago
parent
commit
d772cff00c

+ 18 - 18
Rx.NET/Source/src/System.Reactive/Linq/IQueryLanguage.cs

@@ -193,27 +193,27 @@ namespace System.Reactive.Linq
         IObservable<TSource> Start<TSource>(Func<TSource> function);
         IObservable<TSource> Start<TSource>(Func<TSource> function);
         IObservable<TSource> Start<TSource>(Func<TSource> function, IScheduler scheduler);
         IObservable<TSource> Start<TSource>(Func<TSource> function, IScheduler scheduler);
 
 
-        IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync);
-        IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync);
-        IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync, IScheduler scheduler);
-        IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync, IScheduler scheduler);
+        IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe);
 
 
         IObservable<Unit> Start(Action action);
         IObservable<Unit> Start(Action action);
         IObservable<Unit> Start(Action action, IScheduler scheduler);
         IObservable<Unit> Start(Action action, IScheduler scheduler);
 
 
-        IObservable<Unit> StartAsync(Func<Task> actionAsync);
-        IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync);
-        IObservable<Unit> StartAsync(Func<Task> actionAsync, IScheduler scheduler);
-        IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync, IScheduler scheduler);
+        IObservable<Unit> StartAsync(Func<Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<Unit> StartAsync(Func<Task> actionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe);
 
 
-        IObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync);
-        IObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync);
-        IObservable<Unit> FromAsync(Func<Task> actionAsync);
-        IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync);
-        IObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync, IScheduler scheduler);
-        IObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync, IScheduler scheduler);
-        IObservable<Unit> FromAsync(Func<Task> actionAsync, IScheduler scheduler);
-        IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync, IScheduler scheduler);
+        IObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<Unit> FromAsync(Func<Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<Unit> FromAsync(Func<Task> actionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe);
 
 
         Func<IObservable<TResult>> ToAsync<TResult>(Func<TResult> function);
         Func<IObservable<TResult>> ToAsync<TResult>(Func<TResult> function);
         Func<IObservable<TResult>> ToAsync<TResult>(Func<TResult> function, IScheduler scheduler);
         Func<IObservable<TResult>> ToAsync<TResult>(Func<TResult> function, IScheduler scheduler);
@@ -398,8 +398,8 @@ namespace System.Reactive.Linq
 
 
         IObservable<TValue> Defer<TValue>(Func<IObservable<TValue>> observableFactory);
         IObservable<TValue> Defer<TValue>(Func<IObservable<TValue>> observableFactory);
 
 
-        IObservable<TValue> Defer<TValue>(Func<Task<IObservable<TValue>>> observableFactoryAsync);
-        IObservable<TValue> Defer<TValue>(Func<CancellationToken, Task<IObservable<TValue>>> observableFactoryAsync);
+        IObservable<TValue> Defer<TValue>(Func<Task<IObservable<TValue>>> observableFactoryAsync, bool ignoreExceptionsAfterUnsubscribe);
+        IObservable<TValue> Defer<TValue>(Func<CancellationToken, Task<IObservable<TValue>>> observableFactoryAsync, bool ignoreExceptionsAfterUnsubscribe);
 
 
         IObservable<TResult> Empty<TResult>();
         IObservable<TResult> Empty<TResult>();
         IObservable<TResult> Empty<TResult>(IScheduler scheduler);
         IObservable<TResult> Empty<TResult>(IScheduler scheduler);

+ 16 - 16
Rx.NET/Source/src/System.Reactive/Linq/Observable.Async.cs

@@ -1066,7 +1066,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(functionAsync));
                 throw new ArgumentNullException(nameof(functionAsync));
             }
             }
 
 
-            return s_impl.StartAsync(functionAsync);
+            return s_impl.StartAsync(functionAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1119,7 +1119,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return s_impl.StartAsync(functionAsync, scheduler);
+            return s_impl.StartAsync(functionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1181,7 +1181,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(functionAsync));
                 throw new ArgumentNullException(nameof(functionAsync));
             }
             }
 
 
-            return s_impl.StartAsync(functionAsync);
+            return s_impl.StartAsync(functionAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1250,7 +1250,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return s_impl.StartAsync(functionAsync, scheduler);
+            return s_impl.StartAsync(functionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         #endregion
         #endregion
@@ -1348,7 +1348,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(actionAsync));
                 throw new ArgumentNullException(nameof(actionAsync));
             }
             }
 
 
-            return s_impl.StartAsync(actionAsync);
+            return s_impl.StartAsync(actionAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1399,7 +1399,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return s_impl.StartAsync(actionAsync, scheduler);
+            return s_impl.StartAsync(actionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1459,7 +1459,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(actionAsync));
                 throw new ArgumentNullException(nameof(actionAsync));
             }
             }
 
 
-            return s_impl.StartAsync(actionAsync);
+            return s_impl.StartAsync(actionAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1526,7 +1526,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return s_impl.StartAsync(actionAsync, scheduler);
+            return s_impl.StartAsync(actionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         #endregion
         #endregion
@@ -1569,7 +1569,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(functionAsync));
                 throw new ArgumentNullException(nameof(functionAsync));
             }
             }
 
 
-            return s_impl.FromAsync(functionAsync);
+            return s_impl.FromAsync(functionAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1610,7 +1610,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return s_impl.FromAsync(functionAsync, scheduler);
+            return s_impl.FromAsync(functionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1648,7 +1648,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(functionAsync));
                 throw new ArgumentNullException(nameof(functionAsync));
             }
             }
 
 
-            return s_impl.FromAsync(functionAsync);
+            return s_impl.FromAsync(functionAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1693,7 +1693,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return s_impl.FromAsync(functionAsync, scheduler);
+            return s_impl.FromAsync(functionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         #endregion
         #endregion
@@ -1729,7 +1729,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(actionAsync));
                 throw new ArgumentNullException(nameof(actionAsync));
             }
             }
 
 
-            return s_impl.FromAsync(actionAsync);
+            return s_impl.FromAsync(actionAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1768,7 +1768,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return s_impl.FromAsync(actionAsync, scheduler);
+            return s_impl.FromAsync(actionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1804,7 +1804,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(actionAsync));
                 throw new ArgumentNullException(nameof(actionAsync));
             }
             }
 
 
-            return s_impl.FromAsync(actionAsync);
+            return s_impl.FromAsync(actionAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -1847,7 +1847,7 @@ namespace System.Reactive.Linq
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return s_impl.FromAsync(actionAsync, scheduler);
+            return s_impl.FromAsync(actionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         #endregion
         #endregion

+ 40 - 2
Rx.NET/Source/src/System.Reactive/Linq/Observable.Creation.cs

@@ -208,13 +208,31 @@ namespace System.Reactive.Linq
         /// <exception cref="ArgumentNullException"><paramref name="observableFactoryAsync"/> is null.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="observableFactoryAsync"/> is null.</exception>
         /// <remarks>This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.</remarks>
         /// <remarks>This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.</remarks>
         public static IObservable<TResult> Defer<TResult>(Func<Task<IObservable<TResult>>> observableFactoryAsync)
         public static IObservable<TResult> Defer<TResult>(Func<Task<IObservable<TResult>>> observableFactoryAsync)
+        {
+            return Defer(observableFactoryAsync, ignoreExceptionsAfterUnsubscribe: false);
+        }
+
+        /// <summary>
+        /// Returns an observable sequence that starts the specified asynchronous factory function whenever a new observer subscribes.
+        /// </summary>
+        /// <typeparam name="TResult">The type of the elements in the sequence returned by the factory function, and in the resulting sequence.</typeparam>
+        /// <param name="observableFactoryAsync">Asynchronous factory function to start for each observer that subscribes to the resulting sequence.</param>
+        /// <param name="ignoreExceptionsAfterUnsubscribe">
+        /// If true, exceptions that occur after cancellation has been initiated by unsubscribing from the observable
+        /// this method returns will be handled and silently ignored. If false, they will go unobserved, meaning they
+        /// will eventually emerge through <see cref="TaskScheduler.UnobservedTaskException"/>.
+        /// </param>
+        /// <returns>An observable sequence whose observers trigger the given asynchronous observable factory function to be started.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="observableFactoryAsync"/> is null.</exception>
+        /// <remarks>This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.</remarks>
+        public static IObservable<TResult> Defer<TResult>(Func<Task<IObservable<TResult>>> observableFactoryAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             if (observableFactoryAsync == null)
             if (observableFactoryAsync == null)
             {
             {
                 throw new ArgumentNullException(nameof(observableFactoryAsync));
                 throw new ArgumentNullException(nameof(observableFactoryAsync));
             }
             }
 
 
-            return s_impl.Defer(observableFactoryAsync);
+            return s_impl.Defer(observableFactoryAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -228,13 +246,33 @@ namespace System.Reactive.Linq
         /// <remarks>This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.</remarks>
         /// <remarks>This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.</remarks>
         /// <remarks>When a subscription to the resulting sequence is disposed, the CancellationToken that was fed to the asynchronous observable factory function will be signaled.</remarks>
         /// <remarks>When a subscription to the resulting sequence is disposed, the CancellationToken that was fed to the asynchronous observable factory function will be signaled.</remarks>
         public static IObservable<TResult> DeferAsync<TResult>(Func<CancellationToken, Task<IObservable<TResult>>> observableFactoryAsync)
         public static IObservable<TResult> DeferAsync<TResult>(Func<CancellationToken, Task<IObservable<TResult>>> observableFactoryAsync)
+        {
+            return DeferAsync(observableFactoryAsync, ignoreExceptionsAfterUnsubscribe: false);
+        }
+
+        /// <summary>
+        /// Returns an observable sequence that starts the specified cancellable asynchronous factory function whenever a new observer subscribes.
+        /// The CancellationToken passed to the asynchronous factory function is tied to the returned disposable subscription, allowing best-effort cancellation.
+        /// </summary>
+        /// <typeparam name="TResult">The type of the elements in the sequence returned by the factory function, and in the resulting sequence.</typeparam>
+        /// <param name="observableFactoryAsync">Asynchronous factory function to start for each observer that subscribes to the resulting sequence.</param>
+        /// <param name="ignoreExceptionsAfterUnsubscribe">
+        /// If true, exceptions that occur after cancellation has been initiated by unsubscribing from the observable
+        /// this method returns will be handled and silently ignored. If false, they will go unobserved, meaning they
+        /// will eventually emerge through <see cref="TaskScheduler.UnobservedTaskException"/>.
+        /// </param>
+        /// <returns>An observable sequence whose observers trigger the given asynchronous observable factory function to be started.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="observableFactoryAsync"/> is null.</exception>
+        /// <remarks>This operator is especially useful in conjunction with the asynchronous programming features introduced in C# 5.0 and Visual Basic 11.</remarks>
+        /// <remarks>When a subscription to the resulting sequence is disposed, the CancellationToken that was fed to the asynchronous observable factory function will be signaled.</remarks>
+        public static IObservable<TResult> DeferAsync<TResult>(Func<CancellationToken, Task<IObservable<TResult>>> observableFactoryAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             if (observableFactoryAsync == null)
             if (observableFactoryAsync == null)
             {
             {
                 throw new ArgumentNullException(nameof(observableFactoryAsync));
                 throw new ArgumentNullException(nameof(observableFactoryAsync));
             }
             }
 
 
-            return s_impl.Defer(observableFactoryAsync);
+            return s_impl.Defer(observableFactoryAsync, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         #endregion
         #endregion

+ 44 - 44
Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Async.cs

@@ -658,17 +658,17 @@ namespace System.Reactive.Linq
             return ToAsync(function, scheduler)();
             return ToAsync(function, scheduler)();
         }
         }
 
 
-        public virtual IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync)
+        public virtual IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return StartAsyncImpl(functionAsync, null);
+            return StartAsyncImpl(functionAsync, null, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        public virtual IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync, IScheduler scheduler)
+        public virtual IObservable<TSource> StartAsync<TSource>(Func<Task<TSource>> functionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return StartAsyncImpl(functionAsync, scheduler);
+            return StartAsyncImpl(functionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        private IObservable<TSource> StartAsyncImpl<TSource>(Func<Task<TSource>> functionAsync, IScheduler? scheduler)
+        private IObservable<TSource> StartAsyncImpl<TSource>(Func<Task<TSource>> functionAsync, IScheduler? scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             Task<TSource> task;
             Task<TSource> task;
             try
             try
@@ -682,23 +682,23 @@ namespace System.Reactive.Linq
 
 
             if (scheduler != null)
             if (scheduler != null)
             {
             {
-                return task.ToObservable(scheduler);
+                return task.ToObservable(scheduler, ignoreExceptionsAfterUnsubscribe);
             }
             }
             
             
-            return task.ToObservable();
+            return task.ToObservable(ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        public virtual IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync)
+        public virtual IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return StartAsyncImpl(functionAsync, null);
+            return StartAsyncImpl(functionAsync, null, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        public virtual IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync, IScheduler scheduler)
+        public virtual IObservable<TSource> StartAsync<TSource>(Func<CancellationToken, Task<TSource>> functionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return StartAsyncImpl(functionAsync, scheduler);
+            return StartAsyncImpl(functionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        private IObservable<TSource> StartAsyncImpl<TSource>(Func<CancellationToken, Task<TSource>> functionAsync, IScheduler? scheduler)
+        private IObservable<TSource> StartAsyncImpl<TSource>(Func<CancellationToken, Task<TSource>> functionAsync, IScheduler? scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             var cancellable = new CancellationDisposable();
             var cancellable = new CancellationDisposable();
 
 
@@ -716,11 +716,11 @@ namespace System.Reactive.Linq
 
 
             if (scheduler != null)
             if (scheduler != null)
             {
             {
-                result = task.ToObservable(scheduler);
+                result = task.ToObservable(scheduler, ignoreExceptionsAfterUnsubscribe);
             }
             }
             else
             else
             {
             {
-                result = task.ToObservable();
+                result = task.ToObservable(ignoreExceptionsAfterUnsubscribe);
             }
             }
 
 
             return new StartAsyncObservable<TSource>(cancellable, result);
             return new StartAsyncObservable<TSource>(cancellable, result);
@@ -761,17 +761,17 @@ namespace System.Reactive.Linq
             return ToAsync(action, scheduler)();
             return ToAsync(action, scheduler)();
         }
         }
 
 
-        public virtual IObservable<Unit> StartAsync(Func<Task> actionAsync)
+        public virtual IObservable<Unit> StartAsync(Func<Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return StartAsyncImpl(actionAsync, null);
+            return StartAsyncImpl(actionAsync, null, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        public virtual IObservable<Unit> StartAsync(Func<Task> actionAsync, IScheduler scheduler)
+        public virtual IObservable<Unit> StartAsync(Func<Task> actionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return StartAsyncImpl(actionAsync, scheduler);
+            return StartAsyncImpl(actionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        private IObservable<Unit> StartAsyncImpl(Func<Task> actionAsync, IScheduler? scheduler)
+        private IObservable<Unit> StartAsyncImpl(Func<Task> actionAsync, IScheduler? scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             Task task;
             Task task;
             try
             try
@@ -785,23 +785,23 @@ namespace System.Reactive.Linq
 
 
             if (scheduler != null)
             if (scheduler != null)
             {
             {
-                return task.ToObservable(scheduler);
+                return task.ToObservable(scheduler, ignoreExceptionsAfterUnsubscribe);
             }
             }
             
             
-            return task.ToObservable();
+            return task.ToObservable(ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        public virtual IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync)
+        public virtual IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return StartAsyncImpl(actionAsync, null);
+            return StartAsyncImpl(actionAsync, null, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        public virtual IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync, IScheduler scheduler)
+        public virtual IObservable<Unit> StartAsync(Func<CancellationToken, Task> actionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return StartAsyncImpl(actionAsync, scheduler);
+            return StartAsyncImpl(actionAsync, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        private IObservable<Unit> StartAsyncImpl(Func<CancellationToken, Task> actionAsync, IScheduler? scheduler)
+        private IObservable<Unit> StartAsyncImpl(Func<CancellationToken, Task> actionAsync, IScheduler? scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             var cancellable = new CancellationDisposable();
             var cancellable = new CancellationDisposable();
 
 
@@ -819,11 +819,11 @@ namespace System.Reactive.Linq
 
 
             if (scheduler != null)
             if (scheduler != null)
             {
             {
-                result = task.ToObservable(scheduler);
+                result = task.ToObservable(scheduler, ignoreExceptionsAfterUnsubscribe);
             }
             }
             else
             else
             {
             {
-                result = task.ToObservable();
+                result = task.ToObservable(ignoreExceptionsAfterUnsubscribe);
             }
             }
 
 
             return new StartAsyncObservable<Unit>(cancellable, result);
             return new StartAsyncObservable<Unit>(cancellable, result);
@@ -837,48 +837,48 @@ namespace System.Reactive.Linq
 
 
         #region Func
         #region Func
 
 
-        public virtual IObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync)
+        public virtual IObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(functionAsync));
+            return Defer(() => StartAsync(functionAsync, ignoreExceptionsAfterUnsubscribe));
         }
         }
 
 
-        public virtual IObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync)
+        public virtual IObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(functionAsync));
+            return Defer(() => StartAsync(functionAsync, ignoreExceptionsAfterUnsubscribe));
         }
         }
 
 
-        public virtual IObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync, IScheduler scheduler)
+        public virtual IObservable<TResult> FromAsync<TResult>(Func<Task<TResult>> functionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(functionAsync, scheduler));
+            return Defer(() => StartAsync(functionAsync, scheduler, ignoreExceptionsAfterUnsubscribe));
         }
         }
 
 
-        public virtual IObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync, IScheduler scheduler)
+        public virtual IObservable<TResult> FromAsync<TResult>(Func<CancellationToken, Task<TResult>> functionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(functionAsync, scheduler));
+            return Defer(() => StartAsync(functionAsync, scheduler, ignoreExceptionsAfterUnsubscribe));
         }
         }
 
 
         #endregion
         #endregion
 
 
         #region Action
         #region Action
 
 
-        public virtual IObservable<Unit> FromAsync(Func<Task> actionAsync)
+        public virtual IObservable<Unit> FromAsync(Func<Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(actionAsync));
+            return Defer(() => StartAsync(actionAsync, ignoreExceptionsAfterUnsubscribe));
         }
         }
 
 
-        public virtual IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync)
+        public virtual IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(actionAsync));
+            return Defer(() => StartAsync(actionAsync, ignoreExceptionsAfterUnsubscribe));
         }
         }
 
 
-        public virtual IObservable<Unit> FromAsync(Func<Task> actionAsync, IScheduler scheduler)
+        public virtual IObservable<Unit> FromAsync(Func<Task> actionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(actionAsync, scheduler));
+            return Defer(() => StartAsync(actionAsync, scheduler, ignoreExceptionsAfterUnsubscribe));
         }
         }
 
 
-        public virtual IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync, IScheduler scheduler)
+        public virtual IObservable<Unit> FromAsync(Func<CancellationToken, Task> actionAsync, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(actionAsync, scheduler));
+            return Defer(() => StartAsync(actionAsync, scheduler, ignoreExceptionsAfterUnsubscribe));
         }
         }
 
 
         #endregion
         #endregion

+ 4 - 4
Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Creation.cs

@@ -299,14 +299,14 @@ namespace System.Reactive.Linq
 
 
         #region + DeferAsync +
         #region + DeferAsync +
 
 
-        public virtual IObservable<TValue> Defer<TValue>(Func<Task<IObservable<TValue>>> observableFactoryAsync)
+        public virtual IObservable<TValue> Defer<TValue>(Func<Task<IObservable<TValue>>> observableFactoryAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(observableFactoryAsync).Merge());
+            return Defer(() => StartAsync(observableFactoryAsync, ignoreExceptionsAfterUnsubscribe).Merge());
         }
         }
 
 
-        public virtual IObservable<TValue> Defer<TValue>(Func<CancellationToken, Task<IObservable<TValue>>> observableFactoryAsync)
+        public virtual IObservable<TValue> Defer<TValue>(Func<CancellationToken, Task<IObservable<TValue>>> observableFactoryAsync, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
-            return Defer(() => StartAsync(observableFactoryAsync).Merge());
+            return Defer(() => StartAsync(observableFactoryAsync, ignoreExceptionsAfterUnsubscribe).Merge());
         }
         }
 
 
         #endregion
         #endregion

+ 97 - 10
Rx.NET/Source/src/System.Reactive/Threading/Tasks/TaskObservableExtensions.cs

@@ -20,11 +20,13 @@ namespace System.Reactive.Threading.Tasks
         {
         {
             private readonly Task _task;
             private readonly Task _task;
             private readonly IScheduler? _scheduler;
             private readonly IScheduler? _scheduler;
+            private readonly bool _ignoreExceptionsAfterUnsubscribe;
 
 
-            public SlowTaskObservable(Task task, IScheduler? scheduler)
+            public SlowTaskObservable(Task task, IScheduler? scheduler, bool ignoreExceptionsAfterUnsubscribe)
             {
             {
                 _task = task;
                 _task = task;
                 _scheduler = scheduler;
                 _scheduler = scheduler;
+                _ignoreExceptionsAfterUnsubscribe = ignoreExceptionsAfterUnsubscribe;
             }
             }
 
 
             public IDisposable Subscribe(IObserver<Unit> observer)
             public IDisposable Subscribe(IObserver<Unit> observer)
@@ -52,6 +54,11 @@ namespace System.Reactive.Threading.Tasks
                         options);
                         options);
                 }
                 }
 
 
+                if (_ignoreExceptionsAfterUnsubscribe)
+                {
+                    _task.ContinueWith(t => _ = t.Exception, TaskContinuationOptions.OnlyOnFaulted);
+                }
+
                 return cts;
                 return cts;
             }
             }
         }
         }
@@ -60,11 +67,13 @@ namespace System.Reactive.Threading.Tasks
         {
         {
             private readonly Task<TResult> _task;
             private readonly Task<TResult> _task;
             private readonly IScheduler? _scheduler;
             private readonly IScheduler? _scheduler;
+            private readonly bool _ignoreExceptionsAfterUnsubscribe;
 
 
-            public SlowTaskObservable(Task<TResult> task, IScheduler? scheduler)
+            public SlowTaskObservable(Task<TResult> task, IScheduler? scheduler, bool ignoreExceptionsAfterUnsubscribe)
             {
             {
                 _task = task;
                 _task = task;
                 _scheduler = scheduler;
                 _scheduler = scheduler;
+                _ignoreExceptionsAfterUnsubscribe = ignoreExceptionsAfterUnsubscribe;
             }
             }
 
 
             public IDisposable Subscribe(IObserver<TResult> observer)
             public IDisposable Subscribe(IObserver<TResult> observer)
@@ -92,9 +101,15 @@ namespace System.Reactive.Threading.Tasks
                         options);
                         options);
                 }
                 }
 
 
+                if (_ignoreExceptionsAfterUnsubscribe)
+                {
+                    _task.ContinueWith(t => _ = t.Exception, TaskContinuationOptions.OnlyOnFaulted);
+                }
+
                 return cts;
                 return cts;
             }
             }
         }
         }
+
         /// <summary>
         /// <summary>
         /// Returns an observable sequence that signals when the task completes.
         /// Returns an observable sequence that signals when the task completes.
         /// </summary>
         /// </summary>
@@ -103,13 +118,30 @@ namespace System.Reactive.Threading.Tasks
         /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c>.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c>.</exception>
         /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync(Func{CancellationToken, Task})"/> instead.</remarks>
         /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync(Func{CancellationToken, Task})"/> instead.</remarks>
         public static IObservable<Unit> ToObservable(this Task task)
         public static IObservable<Unit> ToObservable(this Task task)
+        {
+            return ToObservable(task, ignoreExceptionsAfterUnsubscribe: false);
+        }
+
+        /// <summary>
+        /// Returns an observable sequence that signals when the task completes.
+        /// </summary>
+        /// <param name="task">Task to convert to an observable sequence.</param>
+        /// <param name="ignoreExceptionsAfterUnsubscribe">
+        /// If true, exceptions that occur after cancellation has been initiated by unsubscribing from the observable
+        /// this method returns will be handled and silently ignored. If false, they will go unobserved, meaning they
+        /// will eventually emerge through <see cref="TaskScheduler.UnobservedTaskException"/>.
+        /// </param>
+        /// <returns>An observable sequence that produces a unit value when the task completes, or propagates the exception produced by the task.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c>.</exception>
+        /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync(Func{CancellationToken, Task})"/> instead.</remarks>
+        public static IObservable<Unit> ToObservable(this Task task, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             if (task == null)
             if (task == null)
             {
             {
                 throw new ArgumentNullException(nameof(task));
                 throw new ArgumentNullException(nameof(task));
             }
             }
 
 
-            return ToObservableImpl(task, scheduler: null);
+            return ToObservableImpl(task, scheduler: null, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -121,6 +153,24 @@ namespace System.Reactive.Threading.Tasks
         /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c> or <paramref name="scheduler"/> is <c>null</c>.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c> or <paramref name="scheduler"/> is <c>null</c>.</exception>
         /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync(Func{CancellationToken, Task})"/> instead.</remarks>
         /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync(Func{CancellationToken, Task})"/> instead.</remarks>
         public static IObservable<Unit> ToObservable(this Task task, IScheduler scheduler)
         public static IObservable<Unit> ToObservable(this Task task, IScheduler scheduler)
+        {
+            return ToObservable(task, scheduler, ignoreExceptionsAfterUnsubscribe: false);
+        }
+
+        /// <summary>
+        /// Returns an observable sequence that signals when the task completes.
+        /// </summary>
+        /// <param name="task">Task to convert to an observable sequence.</param>
+        /// <param name="scheduler">Scheduler on which to notify observers about completion, cancellation or failure.</param>
+        /// <param name="ignoreExceptionsAfterUnsubscribe">
+        /// If true, exceptions that occur after cancellation has been initiated by unsubscribing from the observable
+        /// this method returns will be handled and silently ignored. If false, they will go unobserved, meaning they
+        /// will eventually emerge through <see cref="TaskScheduler.UnobservedTaskException"/>.
+        /// </param>
+        /// <returns>An observable sequence that produces a unit value when the task completes, or propagates the exception produced by the task.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c> or <paramref name="scheduler"/> is <c>null</c>.</exception>
+        /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync(Func{CancellationToken, Task})"/> instead.</remarks>
+        public static IObservable<Unit> ToObservable(this Task task, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             if (task == null)
             if (task == null)
             {
             {
@@ -132,10 +182,10 @@ namespace System.Reactive.Threading.Tasks
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return ToObservableImpl(task, scheduler);
+            return ToObservableImpl(task, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        private static IObservable<Unit> ToObservableImpl(Task task, IScheduler? scheduler)
+        private static IObservable<Unit> ToObservableImpl(Task task, IScheduler? scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             if (task.IsCompleted)
             if (task.IsCompleted)
             {
             {
@@ -149,7 +199,7 @@ namespace System.Reactive.Threading.Tasks
                 };
                 };
             }
             }
 
 
-            return new SlowTaskObservable(task, scheduler);
+            return new SlowTaskObservable(task, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         private static void EmitTaskResult(this Task task, IObserver<Unit> subject)
         private static void EmitTaskResult(this Task task, IObserver<Unit> subject)
@@ -198,13 +248,31 @@ namespace System.Reactive.Threading.Tasks
         /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c>.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c>.</exception>
         /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync{TResult}(Func{CancellationToken, Task{TResult}})"/> instead.</remarks>
         /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync{TResult}(Func{CancellationToken, Task{TResult}})"/> instead.</remarks>
         public static IObservable<TResult> ToObservable<TResult>(this Task<TResult> task)
         public static IObservable<TResult> ToObservable<TResult>(this Task<TResult> task)
+        {
+            return ToObservable(task, ignoreExceptionsAfterUnsubscribe: false);
+        }
+
+        /// <summary>
+        /// Returns an observable sequence that propagates the result of the task.
+        /// </summary>
+        /// <typeparam name="TResult">The type of the result produced by the task.</typeparam>
+        /// <param name="task">Task to convert to an observable sequence.</param>
+        /// <param name="ignoreExceptionsAfterUnsubscribe">
+        /// If true, exceptions that occur after cancellation has been initiated by unsubscribing from the observable
+        /// this method returns will be handled and silently ignored. If false, they will go unobserved, meaning they
+        /// will eventually emerge through <see cref="TaskScheduler.UnobservedTaskException"/>.
+        /// </param>
+        /// <returns>An observable sequence that produces the task's result, or propagates the exception produced by the task.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c>.</exception>
+        /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync{TResult}(Func{CancellationToken, Task{TResult}})"/> instead.</remarks>
+        public static IObservable<TResult> ToObservable<TResult>(this Task<TResult> task, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             if (task == null)
             if (task == null)
             {
             {
                 throw new ArgumentNullException(nameof(task));
                 throw new ArgumentNullException(nameof(task));
             }
             }
 
 
-            return ToObservableImpl(task, scheduler: null);
+            return ToObservableImpl(task, scheduler: null, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -217,6 +285,25 @@ namespace System.Reactive.Threading.Tasks
         /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c> or <paramref name="scheduler"/> is <c>null</c>.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c> or <paramref name="scheduler"/> is <c>null</c>.</exception>
         /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync{TResult}(Func{CancellationToken, Task{TResult}})"/> instead.</remarks>
         /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync{TResult}(Func{CancellationToken, Task{TResult}})"/> instead.</remarks>
         public static IObservable<TResult> ToObservable<TResult>(this Task<TResult> task, IScheduler scheduler)
         public static IObservable<TResult> ToObservable<TResult>(this Task<TResult> task, IScheduler scheduler)
+        {
+            return ToObservable(task, scheduler, ignoreExceptionsAfterUnsubscribe: false);
+        }
+
+        /// <summary>
+        /// Returns an observable sequence that propagates the result of the task.
+        /// </summary>
+        /// <typeparam name="TResult">The type of the result produced by the task.</typeparam>
+        /// <param name="task">Task to convert to an observable sequence.</param>
+        /// <param name="scheduler">Scheduler on which to notify observers about completion, cancellation or failure.</param>
+        /// <param name="ignoreExceptionsAfterUnsubscribe">
+        /// If true, exceptions that occur after cancellation has been initiated by unsubscribing from the observable
+        /// this method returns will be handled and silently ignored. If false, they will go unobserved, meaning they
+        /// will eventually emerge through <see cref="TaskScheduler.UnobservedTaskException"/>.
+        /// </param>
+        /// <returns>An observable sequence that produces the task's result, or propagates the exception produced by the task.</returns>
+        /// <exception cref="ArgumentNullException"><paramref name="task"/> is <c>null</c> or <paramref name="scheduler"/> is <c>null</c>.</exception>
+        /// <remarks>If the specified task object supports cancellation, consider using <see cref="Observable.FromAsync{TResult}(Func{CancellationToken, Task{TResult}})"/> instead.</remarks>
+        public static IObservable<TResult> ToObservable<TResult>(this Task<TResult> task, IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             if (task == null)
             if (task == null)
             {
             {
@@ -228,10 +315,10 @@ namespace System.Reactive.Threading.Tasks
                 throw new ArgumentNullException(nameof(scheduler));
                 throw new ArgumentNullException(nameof(scheduler));
             }
             }
 
 
-            return ToObservableImpl(task, scheduler);
+            return ToObservableImpl(task, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
-        private static IObservable<TResult> ToObservableImpl<TResult>(Task<TResult> task, IScheduler? scheduler)
+        private static IObservable<TResult> ToObservableImpl<TResult>(Task<TResult> task, IScheduler? scheduler, bool ignoreExceptionsAfterUnsubscribe)
         {
         {
             if (task.IsCompleted)
             if (task.IsCompleted)
             {
             {
@@ -245,7 +332,7 @@ namespace System.Reactive.Threading.Tasks
                 };
                 };
             }
             }
 
 
-            return new SlowTaskObservable<TResult>(task, scheduler);
+            return new SlowTaskObservable<TResult>(task, scheduler, ignoreExceptionsAfterUnsubscribe);
         }
         }
 
 
         private static void EmitTaskResult<TResult>(this Task<TResult> task, IObserver<TResult> subject)
         private static void EmitTaskResult<TResult>(this Task<TResult> task, IObserver<TResult> subject)

+ 15 - 1
Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.verified.cs

@@ -990,7 +990,9 @@ namespace System.Reactive.Linq
         public static System.IObservable<TSource> DefaultIfEmpty<TSource>(this System.IObservable<TSource> source, TSource defaultValue) { }
         public static System.IObservable<TSource> DefaultIfEmpty<TSource>(this System.IObservable<TSource> source, TSource defaultValue) { }
         public static System.IObservable<TResult> Defer<TResult>(System.Func<System.IObservable<TResult>> observableFactory) { }
         public static System.IObservable<TResult> Defer<TResult>(System.Func<System.IObservable<TResult>> observableFactory) { }
         public static System.IObservable<TResult> Defer<TResult>(System.Func<System.Threading.Tasks.Task<System.IObservable<TResult>>> observableFactoryAsync) { }
         public static System.IObservable<TResult> Defer<TResult>(System.Func<System.Threading.Tasks.Task<System.IObservable<TResult>>> observableFactoryAsync) { }
+        public static System.IObservable<TResult> Defer<TResult>(System.Func<System.Threading.Tasks.Task<System.IObservable<TResult>>> observableFactoryAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> DeferAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<System.IObservable<TResult>>> observableFactoryAsync) { }
         public static System.IObservable<TResult> DeferAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<System.IObservable<TResult>>> observableFactoryAsync) { }
+        public static System.IObservable<TResult> DeferAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<System.IObservable<TResult>>> observableFactoryAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TSource> Delay<TSource>(this System.IObservable<TSource> source, System.DateTimeOffset dueTime) { }
         public static System.IObservable<TSource> Delay<TSource>(this System.IObservable<TSource> source, System.DateTimeOffset dueTime) { }
         public static System.IObservable<TSource> Delay<TSource>(this System.IObservable<TSource> source, System.TimeSpan dueTime) { }
         public static System.IObservable<TSource> Delay<TSource>(this System.IObservable<TSource> source, System.TimeSpan dueTime) { }
         public static System.IObservable<TSource> Delay<TSource>(this System.IObservable<TSource> source, System.DateTimeOffset dueTime, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TSource> Delay<TSource>(this System.IObservable<TSource> source, System.DateTimeOffset dueTime, System.Reactive.Concurrency.IScheduler scheduler) { }
@@ -1048,15 +1050,19 @@ namespace System.Reactive.Linq
         public static System.Threading.Tasks.Task ForEachAsync<TSource>(this System.IObservable<TSource> source, System.Action<TSource, int> onNext, System.Threading.CancellationToken cancellationToken) { }
         public static System.Threading.Tasks.Task ForEachAsync<TSource>(this System.IObservable<TSource> source, System.Action<TSource, int> onNext, System.Threading.CancellationToken cancellationToken) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.Tasks.Task> actionAsync) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.Tasks.Task> actionAsync) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync) { }
+        public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.Tasks.Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
+        public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> FromAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync) { }
+        public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
+        public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> FromAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         [System.Obsolete(@"This conversion is no longer supported. Replace use of the Begin/End asynchronous method pair with a new Task-based async method, and convert the result using ToObservable. If no Task-based async method is available, use Task.Factory.FromAsync to obtain a Task object.")]
         [System.Obsolete(@"This conversion is no longer supported. Replace use of the Begin/End asynchronous method pair with a new Task-based async method, and convert the result using ToObservable. If no Task-based async method is available, use Task.Factory.FromAsync to obtain a Task object.")]
         public static System.Func<System.IObservable<System.Reactive.Unit>> FromAsyncPattern(System.Func<System.AsyncCallback, object?, System.IAsyncResult> begin, System.Action<System.IAsyncResult> end) { }
         public static System.Func<System.IObservable<System.Reactive.Unit>> FromAsyncPattern(System.Func<System.AsyncCallback, object?, System.IAsyncResult> begin, System.Action<System.IAsyncResult> end) { }
@@ -1382,15 +1388,19 @@ namespace System.Reactive.Linq
         public static System.IObservable<TResult> Start<TResult>(System.Func<TResult> function, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TResult> Start<TResult>(System.Func<TResult> function, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.Tasks.Task> actionAsync) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.Tasks.Task> actionAsync) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync) { }
+        public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.Tasks.Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
+        public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> StartAsync(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task> actionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync) { }
+        public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler) { }
+        public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> StartAsync<TResult>(System.Func<System.Threading.CancellationToken, System.Threading.Tasks.Task<TResult>> functionAsync, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TSource> StartWith<TSource>(this System.IObservable<TSource> source, System.Collections.Generic.IEnumerable<TSource> values) { }
         public static System.IObservable<TSource> StartWith<TSource>(this System.IObservable<TSource> source, System.Collections.Generic.IEnumerable<TSource> values) { }
         public static System.IObservable<TSource> StartWith<TSource>(this System.IObservable<TSource> source, params TSource[] values) { }
         public static System.IObservable<TSource> StartWith<TSource>(this System.IObservable<TSource> source, params TSource[] values) { }
@@ -3128,9 +3138,13 @@ namespace System.Reactive.Threading.Tasks
     public static class TaskObservableExtensions
     public static class TaskObservableExtensions
     {
     {
         public static System.IObservable<System.Reactive.Unit> ToObservable(this System.Threading.Tasks.Task task) { }
         public static System.IObservable<System.Reactive.Unit> ToObservable(this System.Threading.Tasks.Task task) { }
+        public static System.IObservable<System.Reactive.Unit> ToObservable(this System.Threading.Tasks.Task task, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<System.Reactive.Unit> ToObservable(this System.Threading.Tasks.Task task, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<System.Reactive.Unit> ToObservable(this System.Threading.Tasks.Task task, System.Reactive.Concurrency.IScheduler scheduler) { }
+        public static System.IObservable<System.Reactive.Unit> ToObservable(this System.Threading.Tasks.Task task, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> ToObservable<TResult>(this System.Threading.Tasks.Task<TResult> task) { }
         public static System.IObservable<TResult> ToObservable<TResult>(this System.Threading.Tasks.Task<TResult> task) { }
+        public static System.IObservable<TResult> ToObservable<TResult>(this System.Threading.Tasks.Task<TResult> task, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.IObservable<TResult> ToObservable<TResult>(this System.Threading.Tasks.Task<TResult> task, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.IObservable<TResult> ToObservable<TResult>(this System.Threading.Tasks.Task<TResult> task, System.Reactive.Concurrency.IScheduler scheduler) { }
+        public static System.IObservable<TResult> ToObservable<TResult>(this System.Threading.Tasks.Task<TResult> task, System.Reactive.Concurrency.IScheduler scheduler, bool ignoreExceptionsAfterUnsubscribe) { }
         public static System.Threading.Tasks.Task<TResult> ToTask<TResult>(this System.IObservable<TResult> observable) { }
         public static System.Threading.Tasks.Task<TResult> ToTask<TResult>(this System.IObservable<TResult> observable) { }
         public static System.Threading.Tasks.Task<TResult> ToTask<TResult>(this System.IObservable<TResult> observable, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.Threading.Tasks.Task<TResult> ToTask<TResult>(this System.IObservable<TResult> observable, System.Reactive.Concurrency.IScheduler scheduler) { }
         public static System.Threading.Tasks.Task<TResult> ToTask<TResult>(this System.IObservable<TResult> observable, System.Threading.CancellationToken cancellationToken) { }
         public static System.Threading.Tasks.Task<TResult> ToTask<TResult>(this System.IObservable<TResult> observable, System.Threading.CancellationToken cancellationToken) { }
@@ -3160,4 +3174,4 @@ namespace System.Runtime.CompilerServices
             where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
             where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
         public static System.Runtime.CompilerServices.TaskObservableMethodBuilder<T> Create() { }
         public static System.Runtime.CompilerServices.TaskObservableMethodBuilder<T> Create() { }
     }
     }
-}
+}

+ 8 - 2
Rx.NET/Source/tests/Tests.System.Reactive/Tests/TaskObservableExtensionsTest.cs

@@ -37,9 +37,12 @@ namespace ReactiveTests.Tests
             var s = Scheduler.Immediate;
             var s = Scheduler.Immediate;
 
 
             ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task<int>)null));
             ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task<int>)null));
+            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task<int>)null, false));
 
 
             ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task<int>)null, s));
             ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task<int>)null, s));
-            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(_doneTask, default));
+            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task<int>)null, s, false));
+            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(_doneTask, default(IScheduler)));
+            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(_doneTask, default(IScheduler), false));
 
 
             var tcs = new TaskCompletionSource<int>();
             var tcs = new TaskCompletionSource<int>();
             var task = tcs.Task;
             var task = tcs.Task;
@@ -397,9 +400,12 @@ namespace ReactiveTests.Tests
             var s = Scheduler.Immediate;
             var s = Scheduler.Immediate;
 
 
             ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(null));
             ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(null));
+            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(null, false));
 
 
             ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(null, s));
             ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(null, s));
-            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task)_doneTask, default));
+            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable(null, s, false));
+            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task)_doneTask, default(IScheduler)));
+            ReactiveAssert.Throws<ArgumentNullException>(() => TaskObservableExtensions.ToObservable((Task)_doneTask, default(IScheduler), false));
 
 
             var tcs = new TaskCompletionSource<int>();
             var tcs = new TaskCompletionSource<int>();
             Task task = tcs.Task;
             Task task = tcs.Task;