{"record":{"id":"2434c38eba5d87d0","repo":"dotnet/reactive","slug":"source-controlobservable","errorCode":null,"errorMessage":"source","messagePattern":"source","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs","lineNumber":31,"sourceCode":"    public static class ControlObservable\n    {\n        /// <summary>\n        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the Windows Forms message loop associated with the specified control.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence.</typeparam>\n        /// <param name=\"source\">Source sequence.</param>\n        /// <param name=\"control\">Windows Forms control whose associated message loop is used to perform subscription and unsubscription actions on.</param>\n        /// <returns>The source sequence whose subscriptions and unsubscriptions happen on the Windows Forms message loop associated with the specified control.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"control\"/> is null.</exception>\n        /// <remarks>\n        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified control.\n        /// In order to invoke observer callbacks on the specified control, e.g. to render results in a control, use <see cref=\"ObserveOn\"/>.\n        /// </remarks>\n        public static IObservable<TSource> SubscribeOn<TSource>(this IObservable<TSource> source, Control control)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (control == null)\n            {\n                throw new ArgumentNullException(nameof(control));\n            }\n\n            return Synchronization.SubscribeOn(source, new ControlScheduler(control));\n        }\n\n        /// <summary>\n        /// Wraps the source sequence in order to run its observer callbacks on the Windows Forms message loop associated with the specified control.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence.</typeparam>\n        /// <param name=\"source\">Source sequence.</param>\n        /// <param name=\"control\">Windows Forms control whose associated message loop is used to notify observers on.</param>\n        /// <returns>The source sequence whose observations happen on the Windows Forms message loop associated with the specified control.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"control\"/> is null.</exception>","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Platforms/Desktop/Linq/ControlObservable.cs#L13-L49","documentation":"ControlObservable.SubscribeOn is an extension method that marshals subscription of the source sequence onto the Windows Forms control's message loop via a ControlScheduler. It validates both arguments and throws ArgumentNullException naming 'source' when the observable is null. The library cannot wrap a null sequence.","triggerScenarios":"Calling nullSource.SubscribeOn(someControl), often when the observable comes from a method that returned null, a failed service call, or an uninitialized field.","commonSituations":"UI data-binding code where the observable-producing service returns null on error; refactors where a reactive property was never initialized; WinForms screens composed before the data source is ready.","solutions":["Ensure the source IObservable<TSource> is non-null before calling SubscribeOn.","Fix the producer that is returning null instead of a sequence (use Observable.Empty or Observable.Throw).","Guard with a null check or coalesce to an empty sequence before subscribing."],"exampleFix":"// before\nvar sub = maybeSource.SubscribeOn(this.pictureBox);\n// after\nvar sub = (maybeSource ?? Observable.Empty<Image>()).SubscribeOn(this.pictureBox);","handlingStrategy":"validation","validationCode":"if (source == null) source = Observable.Empty<TSource>();\nif (control == null) throw new InvalidOperationException(\"Control not initialized\");\nvar sub = source.SubscribeOn(control);","typeGuard":"static bool CanSubscribeOn<TSource>(IObservable<TSource> source, Control control) => source is not null && control is not null;","tryCatchPattern":"try { var sub = source.SubscribeOn(control); }\ncatch (ArgumentNullException ex) when (ex.ParamName is \"source\" or \"control\") { log.Error($\"SubscribeOn got null {ex.ParamName}\"); }","preventionTips":["Have services return Observable.Empty instead of null","Subscribe only after form initialization (e.g. in OnLoad, not in the constructor)","Use null-coalescing fallbacks at composition sites"],"tags":["argument-null","winforms","rxjs","ui-thread"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}