فهرست منبع

Finish unobsoleting most of the UI support types

Since System.Reactive now has to become a legacy facade, we don't need to go through the contortions required to gradually deprecate the UI types it contains. The new UI-specific packages now contain these types and System.Reactive is now just a facade for these. (With a couple of exceptions - UWP's 'special' ThreadPoolScheduler is problematic, and RemotingObservable is one we're deliberately relegating to only being available through the legacy facade to find out whether anyone is really using it, because nobody should be doing .NET Remoting any more. If necessary we'll introduce a System.Reactive.For.Remoting but I'd prefer not to.)
Ian Griffiths 7 ماه پیش
والد
کامیت
e31dfa17be
23فایلهای تغییر یافته به همراه97 افزوده شده و 1936 حذف شده
  1. 6 1
      .editorconfig
  2. 1 7
      Rx.NET/Source/Directory.build.props
  3. 0 13
      Rx.NET/Source/facades/System.Reactive/GlobalUsings.cs
  4. 0 222
      Rx.NET/Source/facades/System.Reactive/Obsolete/Desktop/Concurrency/DispatcherScheduler.cs
  5. 0 81
      Rx.NET/Source/facades/System.Reactive/Obsolete/Windows/Strings_WindowsThreading.Designer.cs
  6. 0 128
      Rx.NET/Source/facades/System.Reactive/Obsolete/Windows/Strings_WindowsThreading.resx
  7. 17 8
      Rx.NET/Source/facades/System.Reactive/System.Reactive.csproj
  8. 5 0
      Rx.NET/Source/src/System.Reactive.For.Uwp/ThreadPoolTimerExtensions.cs
  9. 5 0
      Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoExtensions.cs
  10. 0 0
      Rx.NET/Source/src/System.Reactive.For.Wpf/Constants.cs
  11. 8 12
      Rx.NET/Source/src/System.Reactive.For.Wpf/DispatcherScheduler.cs
  12. 18 107
      Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.Linq/DispatcherObservable.cs
  13. 0 498
      Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs
  14. 2 0
      Rx.NET/Source/src/System.Reactive.Net/Linq/Observable.Multiple.CombineLatest.cs
  15. 12 0
      Rx.NET/Source/tests/Tests.System.Reactive.Uwp.DeviceRunner/Tests.System.Reactive.Uwp.DeviceRunner.csproj
  16. 1 1
      Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj
  17. 1 268
      Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs
  18. 0 253
      Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs
  19. 4 27
      Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs
  20. 2 0
      Rx.NET/Source/tests/Tests.System.Reactive/Tests/Internal/HalfSerializerTest.cs
  21. 6 120
      Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs
  22. 4 152
      Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs
  23. 5 38
      Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs

+ 6 - 1
.editorconfig

@@ -255,4 +255,9 @@ csharp_space_between_square_brackets = false
 
 # Primary constructors
 # We find these something of a mixed bag.
-dotnet_diagnostic.IDE0290.severity = none
+dotnet_diagnostic.IDE0290.severity = none
+
+# Target-typed new expressions
+# We will probably adopt these at some point, but for some reason the IDE only just started complaining about them,
+# and I don't want to deal with all these while in the middle of the Slight Deunification.
+dotnet_diagnostic.IDE0090.severity = none

+ 1 - 7
Rx.NET/Source/Directory.build.props

@@ -32,16 +32,10 @@
   <ItemGroup>
     <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
     
-    <!--
-    Nerdbank.GitVersioning 3.6.128 injects a reference to a .proj file that doesn't work inside the
-    UWP test runner project. We don't ship that as a NuGet package, so it doesn't matter what its
-    version number is.
-    -->
     <PackageReference
       Include="Nerdbank.GitVersioning"
       Version="3.6.143"
-      PrivateAssets="all"
-      Condition="$(ProjectName) != 'Tests.System.Reactive.Uwp.DeviceRunner'" />
+      PrivateAssets="all" />
   </ItemGroup>
 
   <ItemGroup>

+ 0 - 13
Rx.NET/Source/facades/System.Reactive/GlobalUsings.cs

@@ -1,13 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT License.
-// See the LICENSE file in the project root for more information. 
-
-extern alias SystemReactiveNet;
-
-global using SystemReactiveNet::System.Reactive.Concurrency;
-global using SystemReactiveNet::System.Reactive.Disposables;
-
-namespace System.Reactive.Disposables
-{
-    internal static class Dummy { }
-}

+ 0 - 222
Rx.NET/Source/facades/System.Reactive/Obsolete/Desktop/Concurrency/DispatcherScheduler.cs

@@ -1,222 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT License.
-// See the LICENSE file in the project root for more information. 
-
-#if HAS_WPF
-extern alias SystemReactiveNet;
-
-using SystemReactiveNet::System.Reactive.Concurrency;
-using SystemReactiveNet::System.Reactive.Disposables;
-using System.Threading;
-
-namespace System.Reactive.Concurrency
-{
-    /// <summary>
-    /// Obsolete. The <c>System.Reactive.For.Wpf</c> NuGet package defines a
-    /// <c>DispatcherScheduler</c> class in the <c>System.Reactive.Wpf</c>
-    /// namespace that replaces this class.
-    /// </summary>
-    /// <remarks>
-    /// This will eventually be removed because all UI-framework-specific functionality is being
-    /// removed from <c>System.Reactive</c>. This is necessary to fix problems in which
-    /// <c>System.Reactive</c> causes applications to end up with dependencies on Windows Forms and
-    /// WPF whether they want them or not.
-    /// </remarks>
-    [Obsolete("Use System.Reactive.Wpf.DispatcherScheduler in the System.Reactive.For.Wpf package instead", error: false)]
-    public class DispatcherScheduler : LocalScheduler, ISchedulerPeriodic
-    {
-        /// <summary>
-        /// Gets the scheduler that schedules work on the current <see cref="System.Windows.Threading.Dispatcher"/>.
-        /// </summary>
-        [Obsolete(Constants_WindowsThreading.OBSOLETE_INSTANCE_PROPERTY)]
-        public static DispatcherScheduler Instance => new(System.Windows.Threading.Dispatcher.CurrentDispatcher);
-
-        /// <summary>
-        /// Gets the scheduler that schedules work on the <see cref="System.Windows.Threading.Dispatcher"/> for the current thread.
-        /// </summary>
-        public static DispatcherScheduler Current
-        {
-            get
-            {
-                var dispatcher = System.Windows.Threading.Dispatcher.FromThread(Thread.CurrentThread)
-                    ?? throw new InvalidOperationException(Strings_WindowsThreading.NO_DISPATCHER_CURRENT_THREAD);
-                return new DispatcherScheduler(dispatcher);
-            }
-        }
-
-        /// <summary>
-        /// Constructs a <see cref="DispatcherScheduler"/> that schedules units of work on the given <see cref="System.Windows.Threading.Dispatcher"/>.
-        /// </summary>
-        /// <param name="dispatcher"><see cref="DispatcherScheduler"/> to schedule work on.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="dispatcher"/> is <c>null</c>.</exception>
-        public DispatcherScheduler(System.Windows.Threading.Dispatcher dispatcher)
-        {
-            Dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
-            Priority = System.Windows.Threading.DispatcherPriority.Normal;
-
-        }
-
-        /// <summary>
-        /// Constructs a <see cref="DispatcherScheduler"/> that schedules units of work on the given <see cref="System.Windows.Threading.Dispatcher"/> at the given priority.
-        /// </summary>
-        /// <param name="dispatcher"><see cref="DispatcherScheduler"/> to schedule work on.</param>
-        /// <param name="priority">Priority at which units of work are scheduled.</param>
-        /// <exception cref="ArgumentNullException"><paramref name="dispatcher"/> is <c>null</c>.</exception>
-        public DispatcherScheduler(System.Windows.Threading.Dispatcher dispatcher, System.Windows.Threading.DispatcherPriority priority)
-        {
-            Dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
-            Priority = priority;
-        }
-
-        /// <summary>
-        /// Gets the <see cref="System.Windows.Threading.Dispatcher"/> associated with the <see cref="DispatcherScheduler"/>.
-        /// </summary>
-        public System.Windows.Threading.Dispatcher Dispatcher { get; }
-
-        /// <summary>
-        /// Gets the priority at which work items will be dispatched.
-        /// </summary>
-        public System.Windows.Threading.DispatcherPriority Priority { get; }
-
-        /// <summary>
-        /// Schedules an action to be executed on the dispatcher.
-        /// </summary>
-        /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
-        /// <param name="state">State passed to the action to be executed.</param>
-        /// <param name="action">Action to be executed.</param>
-        /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="action"/> is <c>null</c>.</exception>
-        public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
-        {
-            if (action == null)
-            {
-                throw new ArgumentNullException(nameof(action));
-            }
-
-            var d = new SingleAssignmentDisposable();
-
-            Dispatcher.BeginInvoke(
-                new Action(() =>
-                {
-                    if (!d.IsDisposed)
-                    {
-                        d.Disposable = action(this, state);
-                    }
-                }),
-                Priority
-            );
-
-            return d;
-        }
-
-        /// <summary>
-        /// Schedules an action to be executed after <paramref name="dueTime"/> on the dispatcher, using a <see cref="System.Windows.Threading.DispatcherTimer"/> object.
-        /// </summary>
-        /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
-        /// <param name="state">State passed to the action to be executed.</param>
-        /// <param name="action">Action to be executed.</param>
-        /// <param name="dueTime">Relative time after which to execute the action.</param>
-        /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="action"/> is <c>null</c>.</exception>
-        public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
-        {
-            if (action == null)
-            {
-                throw new ArgumentNullException(nameof(action));
-            }
-
-            var dt = Scheduler.Normalize(dueTime);
-            if (dt.Ticks == 0)
-            {
-                return Schedule(state, action);
-            }
-
-            return ScheduleSlow(state, dt, action);
-        }
-
-        private IDisposable ScheduleSlow<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
-        {
-            var d = new MultipleAssignmentDisposable();
-
-            var timer = new System.Windows.Threading.DispatcherTimer(Priority, Dispatcher);
-
-            timer.Tick += (s, e) =>
-            {
-                var t = Interlocked.Exchange(ref timer, null);
-                if (t != null)
-                {
-                    try
-                    {
-                        d.Disposable = action(this, state);
-                    }
-                    finally
-                    {
-                        t.Stop();
-                        action = static (s, t) => Disposable.Empty;
-                    }
-                }
-            };
-
-            timer.Interval = dueTime;
-            timer.Start();
-
-            d.Disposable = Disposable.Create(() =>
-            {
-                var t = Interlocked.Exchange(ref timer, null);
-                if (t != null)
-                {
-                    t.Stop();
-                    action = static (s, t) => Disposable.Empty;
-                }
-            });
-
-            return d;
-        }
-
-        /// <summary>
-        /// Schedules a periodic piece of work on the dispatcher, using a <see cref="System.Windows.Threading.DispatcherTimer"/> object.
-        /// </summary>
-        /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
-        /// <param name="state">Initial state passed to the action upon the first iteration.</param>
-        /// <param name="period">Period for running the work periodically.</param>
-        /// <param name="action">Action to be executed, potentially updating the state.</param>
-        /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="action"/> is <c>null</c>.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than <see cref="TimeSpan.Zero"/>.</exception>
-        public IDisposable SchedulePeriodic<TState>(TState state, TimeSpan period, Func<TState, TState> action)
-        {
-            if (period < TimeSpan.Zero)
-            {
-                throw new ArgumentOutOfRangeException(nameof(period));
-            }
-
-            if (action == null)
-            {
-                throw new ArgumentNullException(nameof(action));
-            }
-
-            var timer = new System.Windows.Threading.DispatcherTimer(Priority, Dispatcher);
-
-            var state1 = state;
-
-            timer.Tick += (s, e) =>
-            {
-                state1 = action(state1);
-            };
-
-            timer.Interval = period;
-            timer.Start();
-
-            return Disposable.Create(() =>
-            {
-                var t = Interlocked.Exchange(ref timer, null);
-                if (t != null)
-                {
-                    t.Stop();
-                    action = static _ => _;
-                }
-            });
-        }
-    }
-}
-#endif

+ 0 - 81
Rx.NET/Source/facades/System.Reactive/Obsolete/Windows/Strings_WindowsThreading.Designer.cs

@@ -1,81 +0,0 @@
-//------------------------------------------------------------------------------
-// <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.42000
-//
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
-// </auto-generated>
-//------------------------------------------------------------------------------
-
-namespace System.Reactive {
-    using System;
-    
-    
-    /// <summary>
-    ///   A strongly-typed resource class, for looking up localized strings, etc.
-    /// </summary>
-    // This class was auto-generated by the StronglyTypedResourceBuilder
-    // class via a tool like ResGen or Visual Studio.
-    // To add or remove a member, edit your .ResX file then rerun ResGen
-    // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    internal class Strings_WindowsThreading {
-        
-        private static global::System.Resources.ResourceManager resourceMan;
-        
-        private static global::System.Globalization.CultureInfo resourceCulture;
-        
-        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        internal Strings_WindowsThreading() {
-        }
-        
-        /// <summary>
-        ///   Returns the cached ResourceManager instance used by this class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Resources.ResourceManager ResourceManager {
-            get {
-                if (object.ReferenceEquals(resourceMan, null)) {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Reactive.Obsolete.Windows.Strings_WindowsThreading", typeof(Strings_WindowsThreading).Assembly);
-                    resourceMan = temp;
-                }
-                return resourceMan;
-            }
-        }
-        
-        /// <summary>
-        ///   Overrides the current thread's CurrentUICulture property for all
-        ///   resource lookups using this strongly typed resource class.
-        /// </summary>
-        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Globalization.CultureInfo Culture {
-            get {
-                return resourceCulture;
-            }
-            set {
-                resourceCulture = value;
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to The current thread has no Dispatcher associated with it..
-        /// </summary>
-        internal static string NO_DISPATCHER_CURRENT_THREAD {
-            get {
-                return ResourceManager.GetString("NO_DISPATCHER_CURRENT_THREAD", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to No current Window object found to obtain a CoreDispatcher from..
-        /// </summary>
-        internal static string NO_WINDOW_CURRENT {
-            get {
-                return ResourceManager.GetString("NO_WINDOW_CURRENT", resourceCulture);
-            }
-        }
-    }
-}

+ 0 - 128
Rx.NET/Source/facades/System.Reactive/Obsolete/Windows/Strings_WindowsThreading.resx

@@ -1,128 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <data name="NO_DISPATCHER_CURRENT_THREAD" xml:space="preserve">
-    <value>The current thread has no Dispatcher associated with it.</value>
-    <comment>Only on WPF/SL.</comment>
-  </data>
-  <data name="NO_WINDOW_CURRENT" xml:space="preserve">
-    <value>No current Window object found to obtain a CoreDispatcher from.</value>
-    <comment>Only on Jupiter.</comment>
-  </data>
-</root>

+ 17 - 8
Rx.NET/Source/facades/System.Reactive/System.Reactive.csproj

@@ -3,6 +3,8 @@
   <PropertyGroup>
     <TargetFrameworks>netstandard2.0;net472;uap10.0.18362;net6.0;net6.0-windows10.0.19041</TargetFrameworks>
     <Nullable>enable</Nullable>
+
+    <DefineConstants>$(DefineConstants);LEGACY_SYSTEM_REACTIVE_FACADE</DefineConstants>
   </PropertyGroup>
 
   <PropertyGroup>
@@ -44,9 +46,16 @@
   -->
   <ItemGroup>
     <Compile Remove="Obsolete\**\*.*" />
+    <Compile Remove="Obsolete\UWP\Linq\**" />
     <EmbeddedResource Remove="Obsolete\**\*.*" />
+    <EmbeddedResource Remove="Obsolete\UWP\Linq\**" />
     <!-- Workaround so the files appear in VS -->
     <None Include="Obsolete\**\*.*" />
+    <None Include="..\..\src\System.Reactive.For.WindowsRuntime\AsyncInfoExtensions.cs" Link="Obsolete\UWP\AsyncInfoExtensions.cs" />
+    <None Remove="Obsolete\UWP\Linq\**" />
+    <None Update="Obsolete\UWP\Strings_PlatformServices.Designer.cs">
+      <DependentUpon>Obsolete\UWP\Strings_PlatformServices.resx</DependentUpon>
+    </None>
     <None Include="..\..\src\System.Reactive.For.Uwp\Stubs.cs" Link="Obsolete\UWP\Stubs.cs" />
     <None Include="..\..\src\System.Reactive.For.Uwp\ThreadPoolTimerExtensions.cs" Link="Obsolete\UWP\Concurrency\ThreadPoolTimerExtensions.cs" />
     <None Update="Linq\QbservableEx.NAry.tt">
@@ -65,14 +74,20 @@
     <!-- WindowsRuntime (netX.0-windows and UWP) -->
   <ItemGroup Condition=" $(TargetFramework.StartsWith('uap10.0')) or $(TargetFramework.StartsWith('net6.0-windows')) or $(TargetFramework.StartsWith('net7.0-windows'))">
     <EmbeddedResource Include="Obsolete\UWP\Strings_PlatformServices.resx" />
+    <Compile Update="Obsolete\UWP\Strings_PlatformServices.Designer.cs">
+      <DependentUpon>Obsolete\UWP\Strings_PlatformServices.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
     <Compile Include="..\..\src\System.Reactive.For.WindowsRuntime\AsyncInfoExtensions.cs" Link="Obsolete\UWP\AsyncInfoExtensions.cs" />
 
     <ProjectReference Include="..\..\src\System.Reactive.For.WindowsRuntime\System.Reactive.For.WindowsRuntime.csproj" />
   </ItemGroup>
 
-  <!-- Windows Forms -->
-  <ItemGroup Condition="'$(TargetFramework)' == 'net472' or $(TargetFramework.StartsWith('net6.0-windows')) or $(TargetFramework.StartsWith('net8.0-windows')) or $(TargetFramework.StartsWith('net9.0-windows'))">
+  <!-- Windows Forms and WPF -->
+  <ItemGroup Condition="('$(TargetFramework)' == 'net472') or $(TargetFramework.StartsWith('net6.0-windows')) or $(TargetFramework.StartsWith('net8.0-windows')) or $(TargetFramework.StartsWith('net9.0-windows'))">
     <ProjectReference Include="..\..\src\System.Reactive.For.WindowsForms\System.Reactive.For.WindowsForms.csproj" />
+    <ProjectReference Include="..\..\src\System.Reactive.For.Wpf\System.Reactive.For.Wpf.csproj" />
   </ItemGroup>
   
   <!-- Windows includes for Desktop and UWP -->
@@ -100,16 +115,10 @@
     <ProjectReference Include="..\..\src\System.Reactive.Net\System.Reactive.Net.csproj">
       <Aliases>SystemReactiveNet</Aliases>
     </ProjectReference>
-
-    <ProjectReference Condition="('$(TargetFramework)' == 'net472') or $(TargetFramework.StartsWith('net6.0-windows'))" Include="..\..\src\System.Reactive.For.WindowsForms\System.Reactive.For.WindowsForms.csproj" />
   </ItemGroup>
 
   <ItemGroup Condition="'$(TargetFramework)'=='uap10.0.18362'">
     <ReferencePath Include="$(TargetPlatformSdkPath)UnionMetadata\10.0.19041.0\Windows.winmd" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Obsolete\UWP\Linq\" />
-  </ItemGroup>
-
 </Project>

+ 5 - 0
Rx.NET/Source/src/System.Reactive.For.Uwp/ThreadPoolTimerExtensions.cs

@@ -2,7 +2,12 @@
 // The .NET Foundation licenses this file to you under the MIT License.
 // See the LICENSE file in the project root for more information. 
 
+#if LEGACY_SYSTEM_REACTIVE_FACADE
+extern alias SystemReactiveNet;
+using SystemReactiveNet::System.Reactive.Disposables;
+#else
 using System.Reactive.Disposables;
+#endif
 
 using Windows.System.Threading;
 

+ 5 - 0
Rx.NET/Source/src/System.Reactive.For.WindowsRuntime/AsyncInfoExtensions.cs

@@ -2,7 +2,12 @@
 // The .NET Foundation licenses this file to you under the MIT License.
 // See the LICENSE file in the project root for more information. 
 
+#if LEGACY_SYSTEM_REACTIVE_FACADE
+extern alias SystemReactiveNet;
+using SystemReactiveNet::System.Reactive.Disposables;
+#else
 using System.Reactive.Disposables;
+#endif
 using Windows.Foundation;
 
 namespace System.Reactive.WindowsRuntime

+ 0 - 0
Rx.NET/Source/facades/System.Reactive/Obsolete/Desktop/Internal/Constants.cs → Rx.NET/Source/src/System.Reactive.For.Wpf/Constants.cs


+ 8 - 12
Rx.NET/Source/src/System.Reactive.For.Wpf/DispatcherScheduler.cs

@@ -3,28 +3,24 @@
 // See the LICENSE file in the project root for more information. 
 
 using System.Reactive.Disposables;
-using System.Reactive.Concurrency;
 using System.Threading;
-using System.Windows.Threading;
 
-namespace System.Reactive.Wpf
+namespace System.Reactive.Concurrency
 {
     /// <summary>
     /// Represents an object that schedules units of work on a <see cref="System.Windows.Threading.Dispatcher"/>.
     /// </summary>
     /// <remarks>
-    /// <para>
-    /// This scheduler type is typically used indirectly through extension methods such as
-    /// <see cref="Linq.WpfDispatcherObservable.ObserveOnWpfDispatcher{TSource}(IObservable{TSource}, Dispatcher)"/> and
-    /// <see cref="Linq.WpfDispatcherObservable.SubscribeOnWpfDispatcher{TSource}(IObservable{TSource}, Dispatcher)"/>
-    /// in cases where you have a <see cref="Dispatcher"/> you want to use, or methods such as
-    /// <see cref="Linq.WpfDispatcherObservable.ObserveOnCurrentWpfDispatcher{TSource}(IObservable{TSource})"/>,
-    /// <see cref="Linq.WpfDispatcherObservable.ObserveOnCurrentWpfDispatcher{TSource}(IObservable{TSource})"/>
-    /// when you want to use the calling thread's Dispatcher.
-    /// </para>
+    /// This scheduler type is typically used indirectly through the <see cref="Linq.DispatcherObservable.ObserveOnDispatcher{TSource}(IObservable{TSource})"/> and <see cref="Linq.DispatcherObservable.SubscribeOnDispatcher{TSource}(IObservable{TSource})"/> methods that use the Dispatcher on the calling thread.
     /// </remarks>
     public class DispatcherScheduler : LocalScheduler, ISchedulerPeriodic
     {
+        /// <summary>
+        /// Gets the scheduler that schedules work on the current <see cref="System.Windows.Threading.Dispatcher"/>.
+        /// </summary>
+        [Obsolete(Constants_WindowsThreading.OBSOLETE_INSTANCE_PROPERTY)]
+        public static DispatcherScheduler Instance => new(System.Windows.Threading.Dispatcher.CurrentDispatcher);
+
         /// <summary>
         /// Gets the scheduler that schedules work on the <see cref="System.Windows.Threading.Dispatcher"/> for the current thread.
         /// </summary>

+ 18 - 107
Rx.NET/Source/facades/System.Reactive/Obsolete/Desktop/Linq/DispatcherObservable.cs → Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.Linq/DispatcherObservable.cs

@@ -9,73 +9,20 @@ using System.Windows.Threading;
 namespace System.Reactive.Linq
 {
     /// <summary>
-    /// Obsolete. The <c>System.Reactive.For.Wpf</c> NuGet package defines a
-    /// <c>WpfDispatcherObservable</c> class that defines new extension methods to be used in
-    /// place of these (also in the <c>System.Reactive.Linq</c> namespace).
+    /// Provides a set of extension methods for scheduling actions performed through observable sequences on UI dispatchers.
     /// </summary>
-    /// <remarks>
-    /// <para>
-    /// The replacement <c>WpfDispatcherObservable</c> class uses different names for extension
-    /// methods. When you migrate to that new class from this obsolete one, you will need to change
-    /// your code to invoke different method names:
-    /// </para>
-    /// <list type="table">
-    ///     <listheader><term>Rx &lt;= 6.0</term><term>Now</term></listheader>
-    ///     <item>
-    ///         <term><c>ObserveOn</c> (except for overload taking a <c>DispatcherScheduler</c></term>
-    ///         <term><c>ObserveOnWpfDispatcher</c></term>
-    ///     </item>
-    ///     <item>
-    ///         <term><c>ObserveOnDispatcher</c></term>
-    ///         <term><c>ObserveOnCurrentWpfDispatcher</c></term>
-    ///     </item>
-    ///     <item>
-    ///         <term><c>SubscribeOn</c> (except for overload taking a <c>DispatcherScheduler</c></term>
-    ///         <term><c>SubscribeOnWpfDispatcher</c></term>
-    ///     </item>
-    ///     <item>
-    ///         <term><c>SubscribeOnDispatcher</c></term>
-    ///         <term><c>SubscribeOnCurrentWpfDispatcher</c></term>
-    ///     </item>
-    /// </list>
-    /// <para>
-    /// The overloads accepting a <see cref="DispatcherScheduler"/> don't need to be renamed because
-    /// there is no scope for ambiguity: if you pass the non-obsolete <see cref="DispatcherScheduler"/>
-    /// defined in this package, you will get the corresponding non-obsolete overload. (Code using
-    /// the old obsolete <c>DispatcherScheduler</c> will get the old obsolete overload.)
-    /// </para>
-    /// <para>
-    /// This will eventually be removed because all UI-framework-specific functionality is being
-    /// removed from <c>System.Reactive</c>. This is necessary to fix problems in which
-    /// <c>System.Reactive</c> causes applications to end up with dependencies on Windows Forms and
-    /// WPF whether they want them or not.
-    /// </para>
-    /// <para>
-    /// Rx defines extension methods for <see cref="IObservable{T}"/> in either the
-    /// <c>System.Reactive.Linq</c> or <c>System</c> namespaces. This means the replacement for
-    /// this obsolete class has to use different names. We need to retain these old obsolete
-    /// extension methods for many years to provide code using Rx with time to adapt, which means
-    /// the new extension methods must coexist with these old obsolete ones. Extension methods
-    /// are awkward to fully qualify, making it easier for migrating code if the new methods have
-    /// visibly different names (and not the same names on a new type).
-    /// </para>
-    /// </remarks>
-    [Obsolete("Use the extension methods defined by the System.Reactive.Linq.WpfDispatcherObservable class in the System.Reactive.For.Wpf package instead", error: false)]
     public static class DispatcherObservable
     {
         #region ObserveOn[Dispatcher]
 
         /// <summary>
-        /// Obsolete. Use the <c>ObserveOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
         /// <param name="dispatcher">Dispatcher whose associated message loop is used to notify observers on.</param>
         /// <returns>The source sequence whose observations happen on the specified dispatcher.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="dispatcher"/> is null.</exception>
-        [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> ObserveOn<TSource>(this IObservable<TSource> source, Dispatcher dispatcher)
         {
             if (source == null)
@@ -92,9 +39,7 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>ObserveOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -102,7 +47,6 @@ namespace System.Reactive.Linq
         /// <param name="priority">Priority to schedule work items at.</param>
         /// <returns>The source sequence whose observations happen on the specified dispatcher.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="dispatcher"/> is null.</exception>
-        [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> ObserveOn<TSource>(this IObservable<TSource> source, Dispatcher dispatcher, DispatcherPriority priority)
         {
             if (source == null)
@@ -119,16 +63,13 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>ObserveOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its observer callbacks on the specified dispatcher scheduler.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
         /// <param name="scheduler">Dispatcher scheduler to notify observers on.</param>
         /// <returns>The source sequence whose observations happen on the specified dispatcher scheduler.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="scheduler"/> is null.</exception>
-        [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> ObserveOn<TSource>(this IObservable<TSource> source, DispatcherScheduler scheduler)
         {
             if (source == null)
@@ -144,17 +85,15 @@ namespace System.Reactive.Linq
             return ObserveOn_(source, scheduler.Dispatcher, scheduler.Priority);
         }
 
+
         /// <summary>
-        /// Obsolete. Use the <c>ObserveOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
         /// <param name="dispatcherObject">Object to get the dispatcher from.</param>
         /// <returns>The source sequence whose observations happen on the specified object's dispatcher.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="dispatcherObject"/> is null.</exception>
-        [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> ObserveOn<TSource>(this IObservable<TSource> source, DispatcherObject dispatcherObject)
         {
             if (source == null)
@@ -171,9 +110,7 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>ObserveOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the specified object.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -181,7 +118,6 @@ namespace System.Reactive.Linq
         /// <param name="priority">Priority to schedule work items at.</param>
         /// <returns>The source sequence whose observations happen on the specified object's dispatcher.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="dispatcherObject"/> is null.</exception>
-        [Obsolete("Use the ObserveOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> ObserveOn<TSource>(this IObservable<TSource> source, DispatcherObject dispatcherObject, DispatcherPriority priority)
         {
             if (source == null)
@@ -197,16 +133,14 @@ namespace System.Reactive.Linq
             return ObserveOn_(source, dispatcherObject.Dispatcher, priority);
         }
 
+
         /// <summary>
-        /// Obsolete. Use the <c>ObserveOnCurrentWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the current thread.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
         /// <returns>The source sequence whose observations happen on the current thread's dispatcher.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
-        [Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> ObserveOnDispatcher<TSource>(this IObservable<TSource> source)
         {
             if (source == null)
@@ -218,16 +152,13 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>ObserveOnCurrentWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher associated with the current thread.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
         /// <param name="priority">Priority to schedule work items at.</param>
         /// <returns>The source sequence whose observations happen on the current thread's dispatcher.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
-        [Obsolete("Use the ObserveOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> ObserveOnDispatcher<TSource>(this IObservable<TSource> source, DispatcherPriority priority)
         {
             if (source == null)
@@ -254,9 +185,7 @@ namespace System.Reactive.Linq
         #region SubscribeOn[Dispatcher]
 
         /// <summary>
-        /// Obsolete. Use the <c>SubscribeOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -267,7 +196,6 @@ namespace System.Reactive.Linq
         /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified dispatcher.
         /// In order to invoke observer callbacks on the specified dispatcher, e.g. to render results in a control, use <see cref="DispatcherObservable.ObserveOn{TSource}(IObservable{TSource}, Dispatcher)"/>.
         /// </remarks>
-        [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> SubscribeOn<TSource>(this IObservable<TSource> source, Dispatcher dispatcher)
         {
             if (source == null)
@@ -284,9 +212,7 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>SubscribeOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -298,7 +224,6 @@ namespace System.Reactive.Linq
         /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified dispatcher.
         /// In order to invoke observer callbacks on the specified dispatcher, e.g. to render results in a control, use <see cref="DispatcherObservable.ObserveOn{TSource}(IObservable{TSource}, Dispatcher, DispatcherPriority)"/>.
         /// </remarks>
-        [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> SubscribeOn<TSource>(this IObservable<TSource> source, Dispatcher dispatcher, DispatcherPriority priority)
         {
             if (source == null)
@@ -314,10 +239,9 @@ namespace System.Reactive.Linq
             return SubscribeOn_(source, dispatcher, priority);
         }
 
+
         /// <summary>
-        /// Obsolete. Use the <c>SubscribeOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified dispatcher scheduler.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -328,7 +252,6 @@ namespace System.Reactive.Linq
         /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified scheduler.
         /// In order to invoke observer callbacks on the specified scheduler, e.g. to render results in a control, use <see cref="DispatcherObservable.ObserveOn{TSource}(IObservable{TSource}, DispatcherScheduler)"/>.
         /// </remarks>
-        [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> SubscribeOn<TSource>(this IObservable<TSource> source, DispatcherScheduler scheduler)
         {
             if (source == null)
@@ -345,9 +268,7 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>SubscribeOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the specified object.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -358,7 +279,6 @@ namespace System.Reactive.Linq
         /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the specified object.
         /// In order to invoke observer callbacks on the dispatcher associated with the specified object, e.g. to render results in a control, use <see cref="DispatcherObservable.ObserveOn{TSource}(IObservable{TSource}, DispatcherObject)"/>.
         /// </remarks>
-        [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> SubscribeOn<TSource>(this IObservable<TSource> source, DispatcherObject dispatcherObject)
         {
             if (source == null)
@@ -375,9 +295,7 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>SubscribeOnWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the specified object.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -389,7 +307,6 @@ namespace System.Reactive.Linq
         /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the specified object.
         /// In order to invoke observer callbacks on the dispatcher associated with the specified object, e.g. to render results in a control, use <see cref="DispatcherObservable.ObserveOn{TSource}(IObservable{TSource}, DispatcherObject, DispatcherPriority)"/>.
         /// </remarks>
-        [Obsolete("Use the SubscribeOnWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> SubscribeOn<TSource>(this IObservable<TSource> source, DispatcherObject dispatcherObject, DispatcherPriority priority)
         {
             if (source == null)
@@ -406,9 +323,7 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>SubscribeOnCurrentWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the current thread.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -418,7 +333,6 @@ namespace System.Reactive.Linq
         /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the current thread.
         /// In order to invoke observer callbacks on the dispatcher associated with the current thread, e.g. to render results in a control, use <see cref="DispatcherObservable.ObserveOnDispatcher{TSource}(IObservable{TSource})"/>.
         /// </remarks>
-        [Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> SubscribeOnDispatcher<TSource>(this IObservable<TSource> source)
         {
             if (source == null)
@@ -430,9 +344,7 @@ namespace System.Reactive.Linq
         }
 
         /// <summary>
-        /// Obsolete. Use the <c>SubscribeOnCurrentWpfDispatcher</c> extension method defined by
-        /// <c>System.Reactive.Linq.WpfDispatcherObservable</c> in the
-        /// <c>System.Reactive.For.Wpf</c> package instead.
+        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the dispatcher associated with the current thread.
         /// </summary>
         /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
         /// <param name="source">Source sequence.</param>
@@ -443,7 +355,6 @@ namespace System.Reactive.Linq
         /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the dispatcher associated with the current thread.
         /// In order to invoke observer callbacks on the dispatcher associated with the current thread, e.g. to render results in a control, use <see cref="DispatcherObservable.ObserveOnDispatcher{TSource}(IObservable{TSource}, DispatcherPriority)"/>.
         /// </remarks>
-        [Obsolete("Use the SubscribeOnCurrentWpfDispatcher extension method defined by System.Reactive.Linq.WpfDispatcherObservable in the System.Reactive.For.Wpf package instead", error: false)]
         public static IObservable<TSource> SubscribeOnDispatcher<TSource>(this IObservable<TSource> source, DispatcherPriority priority)
         {
             if (source == null)

+ 0 - 498
Rx.NET/Source/src/System.Reactive.For.Wpf/System.Reactive.Linq/WpfDispatcherObservable.cs

@@ -1,498 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT License.
-// See the LICENSE file in the project root for more information. 
-
-using System.Windows.Threading;
-
-using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler;
-using Synchronization = System.Reactive.Concurrency.Synchronization;
-
-namespace System.Reactive.Linq
-{
-    /// <summary>
-    /// Provides a set of extension methods for scheduling actions performed through observable
-    /// sequences on UI dispatchers.
-    /// </summary>
-    /// <remarks>
-    /// <para>
-    /// This replaces the obsolete <c>System.Reactive.Linq.ControlObservable</c> class in
-    /// <c>System.Reactive</c>.
-    /// </para>
-    /// </remarks>
-    public static class WpfDispatcherObservable
-
-    {
-        #region ObserveOn[Current]Dispatcher
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its observer callbacks on the specified
-        /// dispatcher.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="dispatcher">Dispatcher whose associated message loop is used to notify observers on.</param>
-        /// <returns>The source sequence whose observations happen on the specified dispatcher.</returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="dispatcher"/> is null.
-        /// </exception>
-        public static IObservable<TSource> ObserveOnWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            Dispatcher dispatcher)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (dispatcher == null)
-            {
-                throw new ArgumentNullException(nameof(dispatcher));
-            }
-
-            return ObserveOn_(source, dispatcher);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its observer callbacks on the specified
-        /// dispatcher.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="dispatcher">Dispatcher whose associated message loop is used to notify observers on.</param>
-        /// <param name="priority">Priority to schedule work items at.</param>
-        /// <returns>The source sequence whose observations happen on the specified dispatcher.</returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="dispatcher"/> is null.
-        /// </exception>
-        public static IObservable<TSource> ObserveOnWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            Dispatcher dispatcher,
-            DispatcherPriority priority)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (dispatcher == null)
-            {
-                throw new ArgumentNullException(nameof(dispatcher));
-            }
-
-            return ObserveOn_(source, dispatcher, priority);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its observer callbacks on the specified
-        /// dispatcher scheduler.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="scheduler">Dispatcher scheduler to notify observers on.</param>
-        /// <returns>The source sequence whose observations happen on the specified dispatcher scheduler.</returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="scheduler"/> is null.
-        /// </exception>
-        public static IObservable<TSource> ObserveOn<TSource>(
-            this IObservable<TSource> source,
-            DispatcherScheduler scheduler)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (scheduler == null)
-            {
-                throw new ArgumentNullException(nameof(scheduler));
-            }
-
-            return ObserveOn_(source, scheduler.Dispatcher, scheduler.Priority);
-        }
-
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher
-        /// associated with the specified object.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="dispatcherObject">Object to get the dispatcher from.</param>
-        /// <returns>The source sequence whose observations happen on the specified object's dispatcher.</returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="dispatcherObject"/> is null.
-        /// </exception>
-        public static IObservable<TSource> ObserveOnWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            DispatcherObject dispatcherObject)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (dispatcherObject == null)
-            {
-                throw new ArgumentNullException(nameof(dispatcherObject));
-            }
-
-            return ObserveOn_(source, dispatcherObject.Dispatcher);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher
-        /// associated with the specified object.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="dispatcherObject">Object to get the dispatcher from.</param>
-        /// <param name="priority">Priority to schedule work items at.</param>
-        /// <returns>The source sequence whose observations happen on the specified object's dispatcher.</returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="dispatcherObject"/> is null.
-        /// </exception>
-        public static IObservable<TSource> ObserveOnWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            DispatcherObject dispatcherObject,
-            DispatcherPriority priority)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (dispatcherObject == null)
-            {
-                throw new ArgumentNullException(nameof(dispatcherObject));
-            }
-
-            return ObserveOn_(source, dispatcherObject.Dispatcher, priority);
-        }
-
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher
-        /// associated with the current thread.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>The source sequence whose observations happen on the current thread's dispatcher.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
-        public static IObservable<TSource> ObserveOnCurrentWpfDispatcher<TSource>(
-            this IObservable<TSource> source)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            return ObserveOn_(source, DispatcherScheduler.Current.Dispatcher);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its observer callbacks on the dispatcher
-        /// associated with the current thread.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="priority">Priority to schedule work items at.</param>
-        /// <returns>The source sequence whose observations happen on the current thread's dispatcher.</returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
-        public static IObservable<TSource> ObserveOnCurrentWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            DispatcherPriority priority)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            return ObserveOn_(source, DispatcherScheduler.Current.Dispatcher, priority);
-        }
-
-        private static IObservable<TSource> ObserveOn_<TSource>(IObservable<TSource> source, Dispatcher dispatcher, DispatcherPriority priority)
-        {
-            return Synchronization.ObserveOn(source, new DispatcherSynchronizationContext(dispatcher, priority));
-        }
-
-
-        private static IObservable<TSource> ObserveOn_<TSource>(IObservable<TSource> source, Dispatcher dispatcher)
-        {
-            return Synchronization.ObserveOn(source, new DispatcherSynchronizationContext(dispatcher));
-        }
-
-        #endregion
-
-        #region SubscribeOn[Dispatcher]
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its subscription and unsubscription logic on
-        /// the specified dispatcher.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="dispatcher">
-        /// Dispatcher whose associated message loop is used to perform subscription and
-        /// unsubscription actions on.
-        /// </param>
-        /// <returns>
-        /// The source sequence whose subscriptions and unsubscriptions happen on the specified dispatcher.
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="dispatcher"/> is null.
-        /// </exception>
-        /// <remarks>
-        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions
-        /// to the source sequence are run on the specified dispatcher. In order to invoke observer
-        /// callbacks on the specified dispatcher, e.g. to render results in a control, use
-        /// <see cref="ObserveOnWpfDispatcher{TSource}(IObservable{TSource}, Dispatcher)"/>.
-        /// </remarks>
-        public static IObservable<TSource> SubscribeOnWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            Dispatcher dispatcher)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (dispatcher == null)
-            {
-                throw new ArgumentNullException(nameof(dispatcher));
-            }
-
-            return SubscribeOn_(source, dispatcher);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its subscription and unsubscription logic on
-        /// the specified dispatcher.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="dispatcher">
-        /// Dispatcher whose associated message loop is used to to perform subscription and
-        /// unsubscription actions on.
-        /// </param>
-        /// <param name="priority">Priority to schedule work items at.</param>
-        /// <returns>
-        /// The source sequence whose subscriptions and unsubscriptions happen on the specified
-        /// dispatcher.
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="dispatcher"/> is null.
-        /// </exception>
-        /// <remarks>
-        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions
-        /// to the source sequence are run on the specified dispatcher. In order to invoke observer
-        /// callbacks on the specified dispatcher, e.g. to render results in a control, use
-        /// <see cref="ObserveOnWpfDispatcher{TSource}(IObservable{TSource}, Dispatcher, DispatcherPriority)"/>.
-        /// </remarks>
-        public static IObservable<TSource> SubscribeOnWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            Dispatcher dispatcher,
-            DispatcherPriority priority)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (dispatcher == null)
-            {
-                throw new ArgumentNullException(nameof(dispatcher));
-            }
-
-            return SubscribeOn_(source, dispatcher, priority);
-        }
-
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its subscription and unsubscription logic on
-        /// the specified dispatcher scheduler.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="scheduler">
-        /// Dispatcher scheduler to perform subscription and unsubscription actions on.
-        /// </param>
-        /// <returns>
-        /// The source sequence whose subscriptions and unsubscriptions happen on the specified
-        /// dispatcher scheduler.
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="scheduler"/> is null.
-        /// </exception>
-        /// <remarks>
-        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions
-        /// to the source sequence are run on the specified scheduler. In order to invoke observer
-        /// callbacks on the specified scheduler, e.g. to render results in a control, use
-        /// <see cref="ObserveOn{TSource}(IObservable{TSource}, DispatcherScheduler)"/>.
-        /// </remarks>
-        public static IObservable<TSource> SubscribeOn<TSource>(
-            this IObservable<TSource> source,
-            DispatcherScheduler scheduler)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (scheduler == null)
-            {
-                throw new ArgumentNullException(nameof(scheduler));
-            }
-
-            return SubscribeOn_(source, scheduler.Dispatcher, scheduler.Priority);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its subscription and unsubscription logic on
-        /// the dispatcher associated with the specified object.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="dispatcherObject">Object to get the dispatcher from.</param>
-        /// <returns>
-        /// The source sequence whose subscriptions and unsubscriptions happen on the specified
-        /// object's dispatcher.
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="dispatcherObject"/> is null.
-        /// </exception>
-        /// <remarks>
-        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions
-        /// to the source sequence are run on the dispatcher associated with the specified object.
-        /// In order to invoke observer callbacks on the dispatcher associated with the specified
-        /// object, e.g. to render results in a control, use
-        /// <see cref="ObserveOnWpfDispatcher{TSource}(IObservable{TSource}, DispatcherObject)"/>.
-        /// </remarks>
-        public static IObservable<TSource> SubscribeOnWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            DispatcherObject dispatcherObject)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (dispatcherObject == null)
-            {
-                throw new ArgumentNullException(nameof(dispatcherObject));
-            }
-
-            return SubscribeOn_(source, dispatcherObject.Dispatcher);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its subscription and unsubscription logic on
-        /// the dispatcher associated with the specified object.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="dispatcherObject">Object to get the dispatcher from.</param>
-        /// <param name="priority">Priority to schedule work items at.</param>
-        /// <returns>
-        /// The source sequence whose subscriptions and unsubscriptions happen on the specified object's dispatcher.
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="source"/> or <paramref name="dispatcherObject"/> is null.
-        /// </exception>
-        /// <remarks>
-        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions
-        /// to the source sequence are run on the dispatcher associated with the specified object.
-        /// In order to invoke observer callbacks on the dispatcher associated with the specified
-        /// object, e.g. to render results in a control, use
-        /// <see cref="ObserveOnWpfDispatcher{TSource}(IObservable{TSource}, DispatcherObject, DispatcherPriority)"/>.
-        /// </remarks>
-        public static IObservable<TSource> SubscribeOnWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            DispatcherObject dispatcherObject,
-            DispatcherPriority priority)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            if (dispatcherObject == null)
-            {
-                throw new ArgumentNullException(nameof(dispatcherObject));
-            }
-
-            return SubscribeOn_(source, dispatcherObject.Dispatcher, priority);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its subscription and unsubscription logic on
-        /// the dispatcher associated with the current thread.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>
-        /// The source sequence whose subscriptions and unsubscriptions happen on the current
-        /// thread's dispatcher.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
-        /// <remarks>
-        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions
-        /// to the source sequence are run on the dispatcher associated with the current thread.
-        /// In order to invoke observer callbacks on the dispatcher associated with the current
-        /// thread, e.g. to render results in a control, use
-        /// <see cref="ObserveOnCurrentWpfDispatcher{TSource}(IObservable{TSource})"/>.
-        /// </remarks>
-        public static IObservable<TSource> SubscribeOnCurrentWpfDispatcher<TSource>(
-            this IObservable<TSource> source)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            return SubscribeOn_(source, DispatcherScheduler.Current.Dispatcher);
-        }
-
-        /// <summary>
-        /// Wraps the source sequence in order to run its subscription and unsubscription logic on
-        /// the dispatcher associated with the current thread.
-        /// </summary>
-        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="priority">Priority to schedule work items at.</param>
-        /// <returns>
-        /// The source sequence whose observations happen on the current thread's dispatcher.
-        /// </returns>
-        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
-        /// <remarks>
-        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions
-        /// to the source sequence are run on the dispatcher associated with the current thread.
-        /// In order to invoke observer callbacks on the dispatcher associated with the current
-        /// thread, e.g. to render results in a control, use
-        /// <see cref="ObserveOnCurrentWpfDispatcher{TSource}(IObservable{TSource}, DispatcherPriority)"/>.
-        /// </remarks>
-        public static IObservable<TSource> SubscribeOnCurrentWpfDispatcher<TSource>(
-            this IObservable<TSource> source,
-            DispatcherPriority priority)
-        {
-            if (source == null)
-            {
-                throw new ArgumentNullException(nameof(source));
-            }
-
-            return SubscribeOn_(source, DispatcherScheduler.Current.Dispatcher, priority);
-        }
-
-        private static IObservable<TSource> SubscribeOn_<TSource>(IObservable<TSource> source, Dispatcher dispatcher, DispatcherPriority priority)
-        {
-            return Synchronization.SubscribeOn(source, new DispatcherSynchronizationContext(dispatcher, priority));
-        }
-
-
-        private static IObservable<TSource> SubscribeOn_<TSource>(IObservable<TSource> source, Dispatcher dispatcher)
-        {
-            return Synchronization.SubscribeOn(source, new DispatcherSynchronizationContext(dispatcher));
-        }
-
-        #endregion
-    }
-}

+ 2 - 0
Rx.NET/Source/src/System.Reactive.Net/Linq/Observable.Multiple.CombineLatest.cs

@@ -1193,7 +1193,9 @@ namespace System.Reactive.Linq
 
     }
 
+#pragma warning disable CA1711 // Identifiers should not have incorrect suffix. It has always been called this, so we can't change it now.
     public static partial class ObservableEx
+#pragma warning restore CA1711 // Identifiers should not have incorrect suffix
     {
         /// <summary>
         /// Merges the specified observable sequences into one observable sequence of tuple values whenever any of the observable sequences produces an element.

+ 12 - 0
Rx.NET/Source/tests/Tests.System.Reactive.Uwp.DeviceRunner/Tests.System.Reactive.Uwp.DeviceRunner.csproj

@@ -147,6 +147,18 @@
     </PackageReference>
     <PackageReference Include="xunit.assert" Version="2.8.0" />
   </ItemGroup>
+  <ItemGroup>
+    <!--
+    Nerdbank.GitVersioning 3.6.128 injects a reference to a .proj file that doesn't work inside the
+    UWP test runner project. We don't ship that as a NuGet package, so it doesn't matter what its
+    version number is.
+    However, this doesn't seem to work. And excluding this project in the Directory.Build.props file
+    where we add this reference in the first place also doesn't work. I think this is coming in
+    transitively. So we need to work out exactly how .nuget\packages\nerdbank.gitversioning\3.6.143\build\PrivateP2PCaching.proj
+    is getting included, and work out how to stop that.
+    -->
+    <PackageReference Remove="Nerdbank.GitVersioning" />
+  </ItemGroup>
   <ItemGroup>
     <ApplicationDefinition Include="App.xaml">
       <Generator>MSBuild:Compile</Generator>

+ 1 - 1
Rx.NET/Source/tests/Tests.System.Reactive/Tests.System.Reactive.csproj

@@ -38,7 +38,7 @@
     <ProjectReference Include="..\..\src\Microsoft.Reactive.Testing\Microsoft.Reactive.Testing.csproj" />
   </ItemGroup>
 
-  <ItemGroup Condition="'$(TargetFramework)' == 'net472' or $(TargetFramework.StartsWith('net8.0-windows')) or $(TargetFramework.StartsWith('net9.0-windows'))">
+  <ItemGroup Condition="('$(TargetFramework)' == 'net472') or $(TargetFramework.StartsWith('net8.0-windows')) or $(TargetFramework.StartsWith('net9.0-windows'))">
     <ProjectReference Include="..\..\src\System.Reactive.For.WindowsForms\System.Reactive.For.WindowsForms.csproj" />
     <ProjectReference Include="..\..\src\System.Reactive.For.Wpf\System.Reactive.For.Wpf.csproj" />
     <PackageReference Update="coverlet.collector" Version="6.0.2">

+ 1 - 268
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/ControlSchedulerTest.cs

@@ -16,9 +16,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Microsoft.Reactive.Testing;
 
 using Assert = Xunit.Assert;
-// TODO: separate out legacy tests into different project? Or, maybe this doesn't need to be legacy.
-using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler;
-using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler;
 
 namespace ReactiveTests.Tests
 {
@@ -30,7 +27,6 @@ namespace ReactiveTests.Tests
         {
 #pragma warning disable CA1806 // (Unused new instance.) We expect the constructor to throw.
             ReactiveAssert.Throws<ArgumentNullException>(() => new ControlScheduler(null));
-            ReactiveAssert.Throws<ArgumentNullException>(() => new LegacyControlScheduler(null));
 #pragma warning restore CA1806
         }
 
@@ -39,7 +35,6 @@ namespace ReactiveTests.Tests
         {
             var lbl = new Label();
             Assert.Same(lbl, new ControlScheduler(lbl).Control);
-            Assert.Same(lbl, new LegacyControlScheduler(lbl).Control);
         }
 
         [TestMethod]
@@ -49,13 +44,6 @@ namespace ReactiveTests.Tests
             Assert.True(res.Seconds < 1);
         }
 
-        [TestMethod]
-        public void NowLegacy()
-        {
-            var res = new LegacyControlScheduler(new Label()).Now - DateTime.Now;
-            Assert.True(res.Seconds < 1);
-        }
-
         [TestMethod]
         public void Schedule_ArgumentChecking()
         {
@@ -65,15 +53,6 @@ namespace ReactiveTests.Tests
             ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
         }
 
-        [TestMethod]
-        public void Schedule_ArgumentChecking_Legacy()
-        {
-            var s = new LegacyControlScheduler(new Label());
-            ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, default(Func<IScheduler, int, IDisposable>)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, TimeSpan.FromSeconds(1), default(Func<IScheduler, int, IDisposable>)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
-        }
-
         [TestMethod]
         public void Schedule()
         {
@@ -84,25 +63,7 @@ namespace ReactiveTests.Tests
                 var id = Environment.CurrentManagedThreadId;
 
                 var sch = new ControlScheduler(lbl);
-                
-                sch.Schedule(() => { lbl.Text = "Okay"; Assert.NotEqual(id, Environment.CurrentManagedThreadId); });
-                sch.Schedule(() => { Assert.Equal("Okay", lbl.Text); Assert.NotEqual(id, Environment.CurrentManagedThreadId); evt.Set(); });
-
-                evt.WaitOne();
-            }
-        }
 
-        [TestMethod]
-        public void Schedule_Legacy()
-        {
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var id = Environment.CurrentManagedThreadId;
-
-                var sch = new LegacyControlScheduler(lbl);
-                
                 sch.Schedule(() => { lbl.Text = "Okay"; Assert.NotEqual(id, Environment.CurrentManagedThreadId); });
                 sch.Schedule(() => { Assert.Equal("Okay", lbl.Text); Assert.NotEqual(id, Environment.CurrentManagedThreadId); evt.Set(); });
 
@@ -135,55 +96,18 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void ScheduleError_Legacy()
-        {
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var ex = new Exception();
-
-                lbl.Invoke(new Action(() =>
-                {
-                    Application.ThreadException += (o, e) =>
-                    {
-                        Assert.Same(ex, e.Exception);
-                        evt.Set();
-                    };
-                }));
-
-                var sch = new LegacyControlScheduler(lbl);
-                sch.Schedule(() => { throw ex; });
-
-                evt.WaitOne();
-            }
-        }
-
         [TestMethod]
         public void ScheduleRelative()
         {
             ScheduleRelative_(TimeSpan.FromSeconds(0.1));
         }
 
-        [TestMethod]
-        public void ScheduleRelative_Legacy()
-        {
-            ScheduleRelative_Legacy_(TimeSpan.FromSeconds(0.1));
-        }
-
         [TestMethod]
         public void ScheduleRelative_Zero()
         {
             ScheduleRelative_(TimeSpan.Zero);
         }
 
-        [TestMethod]
-        public void ScheduleRelative_Zero_Legacy()
-        {
-            ScheduleRelative_Legacy_(TimeSpan.Zero);
-        }
-
         private void ScheduleRelative_(TimeSpan delay)
         {
             using (WinFormsTestUtils.RunTest(out var lbl))
@@ -191,41 +115,14 @@ namespace ReactiveTests.Tests
                 var evt = new ManualResetEvent(false);
 
                 var id = Environment.CurrentManagedThreadId;
-                
+
                 var sch = new ControlScheduler(lbl);
 
                 sch.Schedule(delay, () =>
                 {
                     lbl.Text = "Okay";
                     Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                    
-                    sch.Schedule(() =>
-                    {
-                        Assert.Equal("Okay", lbl.Text);
-                        Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                        evt.Set();
-                    });
-                });
-
-                evt.WaitOne();
-            }
-        }
-
-        private void ScheduleRelative_Legacy_(TimeSpan delay)
-        {
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt = new ManualResetEvent(false);
 
-                var id = Environment.CurrentManagedThreadId;
-                
-                var sch = new LegacyControlScheduler(lbl);
-
-                sch.Schedule(delay, () =>
-                {
-                    lbl.Text = "Okay";
-                    Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                    
                     sch.Schedule(() =>
                     {
                         Assert.Equal("Okay", lbl.Text);
@@ -269,37 +166,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void ScheduleRelative_Nested_Legacy()
-        {
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var id = Environment.CurrentManagedThreadId;
-
-                var sch = new LegacyControlScheduler(lbl);
-
-                sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
-                {
-                    sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
-                    {
-                        lbl.Text = "Okay";
-                        Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-
-                        sch.Schedule(() =>
-                        {
-                            Assert.Equal("Okay", lbl.Text);
-                            Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                            evt.Set();
-                        });
-                    });
-                });
-
-                evt.WaitOne();
-            }
-        }
-
         [TestMethod]
         public void ScheduleRelative_Cancel()
         {
@@ -338,44 +204,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void ScheduleRelative_Cancel_Legacy()
-        {
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var id = Environment.CurrentManagedThreadId;
-
-                var sch = new LegacyControlScheduler(lbl);
-
-                sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
-                {
-                    lbl.Text = "Okay";
-                    Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-
-                    var d = sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
-                    {
-                        lbl.Text = "Oops!";
-                    });
-
-                    sch.Schedule(() =>
-                    {
-                        d.Dispose();
-                    });
-
-                    sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
-                    {
-                        Assert.Equal("Okay", lbl.Text);
-                        Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                        evt.Set();
-                    });
-                });
-
-                evt.WaitOne();
-            }
-        }
-
         [TestMethod]
         public void SchedulePeriodic_ArgumentChecking()
         {
@@ -387,17 +215,6 @@ namespace ReactiveTests.Tests
             ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.FromMilliseconds(1).Subtract(TimeSpan.FromTicks(1)), x => x));
         }
 
-        [TestMethod]
-        public void SchedulePeriodic_ArgumentChecking_Legacy()
-        {
-            var s = new LegacyControlScheduler(new Label());
-#pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested.
-            ReactiveAssert.Throws<ArgumentNullException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
-#pragma warning restore IDE0034
-            ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.Zero, x => x));
-            ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.FromMilliseconds(1).Subtract(TimeSpan.FromTicks(1)), x => x));
-        }
-
         [TestMethod]
         public void SchedulePeriodic()
         {
@@ -440,48 +257,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void SchedulePeriodic_Legacy()
-        {
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var id = Environment.CurrentManagedThreadId;
-
-                var sch = new LegacyControlScheduler(lbl);
-
-                var d = new SingleAssignmentDisposable();
-
-                d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
-                {
-                    lbl.Text = "Okay " + n;
-                    Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-
-                    if (n == 3)
-                    {
-                        d.Dispose();
-
-                        sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
-                        {
-                            Assert.Equal("Okay 3", lbl.Text);
-                            Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                            evt.Set();
-                        });
-                    }
-
-                    if (n > 3)
-                    {
-                        Assert.True(false);
-                    }
-
-                    return n + 1;
-                });
-
-                evt.WaitOne();
-            }
-        }
-
         [TestMethod]
         public void SchedulePeriodic_Nested()
         {
@@ -523,48 +298,6 @@ namespace ReactiveTests.Tests
                 evt.WaitOne();
             }
         }
-
-        [TestMethod]
-        public void SchedulePeriodic_Nested_Legacy()
-        {
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var id = Environment.CurrentManagedThreadId;
-
-                var sch = new LegacyControlScheduler(lbl);
-
-                sch.Schedule(() =>
-                {
-                    lbl.Text = "Okay";
-
-                    var d = new SingleAssignmentDisposable();
-
-                    d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
-                    {
-                        lbl.Text = "Okay " + n;
-                        Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-
-                        if (n == 3)
-                        {
-                            d.Dispose();
-
-                            sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
-                            {
-                                Assert.Equal("Okay 3", lbl.Text);
-                                Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                                evt.Set();
-                            });
-                        }
-
-                        return n + 1;
-                    });
-                });
-
-                evt.WaitOne();
-            }
-        }
     }
 }
 #endif

+ 0 - 253
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/DispatcherSchedulerTest.cs

@@ -16,8 +16,6 @@ using Microsoft.Reactive.Testing;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 using Assert = Xunit.Assert;
-using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler;
-using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler;
 
 namespace ReactiveTests.Tests
 {
@@ -32,14 +30,6 @@ namespace ReactiveTests.Tests
 #pragma warning restore CA1806
         }
 
-        [TestMethod]
-        public void Ctor_ArgumentChecking_Legacy()
-        {
-#pragma warning disable CA1806 // (Unused new instance.) We expect the constructor to throw.
-            ReactiveAssert.Throws<ArgumentNullException>(() => new LegacyDispatcherScheduler(null));
-#pragma warning restore CA1806
-        }
-
         [TestMethod]
         public void Current()
         {
@@ -57,23 +47,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void Current_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var d))
-            {
-                var e = new ManualResetEvent(false);
-
-                d.BeginInvoke(() =>
-                {
-                    var c = LegacyDispatcherScheduler.Current;
-                    c.Schedule(() => { e.Set(); });
-                });
-
-                e.WaitOne();
-            }
-        }
-
         [TestMethod]
         public void Current_None()
         {
@@ -97,29 +70,6 @@ namespace ReactiveTests.Tests
             Assert.True(e != null && e is InvalidOperationException);
         }
 
-        [TestMethod]
-        public void Current_None_Legacy()
-        {
-            var e = default(Exception);
-
-            var t = new Thread(() =>
-            {
-                try
-                {
-                    var ignored = LegacyDispatcherScheduler.Current;
-                }
-                catch (Exception ex)
-                {
-                    e = ex;
-                }
-            });
-
-            t.Start();
-            t.Join();
-
-            Assert.True(e != null && e is InvalidOperationException);
-        }
-
         [TestMethod]
         public void Dispatcher()
         {
@@ -129,15 +79,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void Dispatcher_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                Assert.Same(disp.Dispatcher, new LegacyDispatcherScheduler(disp).Dispatcher);
-            }
-        }
-
         [TestMethod]
         public void Now()
         {
@@ -148,16 +89,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void Now_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                var res = new LegacyDispatcherScheduler(disp).Now - DateTime.Now;
-                Assert.True(res.Seconds < 1);
-            }
-        }
-
         [TestMethod]
         public void Schedule_ArgumentChecking()
         {
@@ -170,18 +101,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void Schedule_ArgumentChecking_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                var s = new LegacyDispatcherScheduler(disp);
-                ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, default(Func<IScheduler, int, IDisposable>)));
-                ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, TimeSpan.FromSeconds(1), default(Func<IScheduler, int, IDisposable>)));
-                ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
-            }
-        }
-
         [TestMethod]
         [Asynchronous]
         public void Schedule()
@@ -201,25 +120,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        [Asynchronous]
-        public void Schedule_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                RunAsync(evt =>
-                {
-                    var id = Environment.CurrentManagedThreadId;
-                    var sch = new LegacyDispatcherScheduler(disp);
-                    sch.Schedule(() =>
-                    {
-                        Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                        evt.Set();
-                    });
-                });
-            }
-        }
-
         [TestMethod]
         public void ScheduleError()
         {
@@ -245,55 +145,18 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void ScheduleError_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                var ex = new Exception();
-
-                var id = Environment.CurrentManagedThreadId;
-                var evt = new ManualResetEvent(false);
-
-                Exception thrownEx = null;
-                disp.UnhandledException += (o, e) =>
-                {
-                    thrownEx = e.Exception;
-                    evt.Set();
-                    e.Handled = true;
-                };
-                var sch = new LegacyDispatcherScheduler(disp);
-                sch.Schedule(() => { throw ex; });
-                evt.WaitOne();
-
-                Assert.Same(ex, thrownEx);
-            }
-        }
-
         [TestMethod]
         public void ScheduleRelative()
         {
             ScheduleRelative_(TimeSpan.FromSeconds(0.2));
         }
 
-        [TestMethod]
-        public void ScheduleRelative_Legacy()
-        {
-            ScheduleRelative_Legacy_(TimeSpan.FromSeconds(0.2));
-        }
-
         [TestMethod]
         public void ScheduleRelative_Zero()
         {
             ScheduleRelative_(TimeSpan.Zero);
         }
 
-        [TestMethod]
-        public void ScheduleRelative_Zero_Legacy()
-        {
-            ScheduleRelative_Legacy_(TimeSpan.Zero);
-        }
-
         private void ScheduleRelative_(TimeSpan delay)
         {
             using (DispatcherHelpers.RunTest(out var disp))
@@ -319,31 +182,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        private void ScheduleRelative_Legacy_(TimeSpan delay)
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var id = Environment.CurrentManagedThreadId;
-
-                var sch = new DispatcherScheduler(disp);
-
-                sch.Schedule(delay, () =>
-                {
-                    Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-
-                    sch.Schedule(delay, () =>
-                    {
-                        Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                        evt.Set();
-                    });
-                });
-
-                evt.WaitOne();
-            }
-        }
-
         [TestMethod]
         public void ScheduleRelative_Cancel()
         {
@@ -381,43 +219,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        public void ScheduleRelative_Cancel_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var id = Environment.CurrentManagedThreadId;
-
-                var sch = new LegacyDispatcherScheduler(disp);
-
-                sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
-                {
-                    Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-
-                    var d = sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
-                    {
-                        Assert.True(false);
-                        evt.Set();
-                    });
-
-                    sch.Schedule(() =>
-                    {
-                        d.Dispose();
-                    });
-
-                    sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
-                    {
-                        Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                        evt.Set();
-                    });
-                });
-
-                evt.WaitOne();
-            }
-        }
-
         [TestMethod]
         public void SchedulePeriodic_ArgumentChecking()
         {
@@ -425,20 +226,6 @@ namespace ReactiveTests.Tests
             {
                 var s = new DispatcherScheduler(disp);
 
-#pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested.
-                ReactiveAssert.Throws<ArgumentNullException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
-#pragma warning restore IDE0034
-                ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(-1), x => x));
-            }
-        }
-
-        [TestMethod]
-        public void SchedulePeriodic_ArgumentChecking_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                var s = new LegacyDispatcherScheduler(disp);
-
 #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested.
                 ReactiveAssert.Throws<ArgumentNullException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
 #pragma warning restore IDE0034
@@ -485,46 +272,6 @@ namespace ReactiveTests.Tests
                 evt.WaitOne();
             }
         }
-
-        [TestMethod]
-        public void SchedulePeriodic_Legacy()
-        {
-            using (DispatcherHelpers.RunTest(out var disp))
-            {
-                var evt = new ManualResetEvent(false);
-
-                var id = Environment.CurrentManagedThreadId;
-
-                var sch = new LegacyDispatcherScheduler(disp);
-
-                var d = new SingleAssignmentDisposable();
-
-                d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
-                {
-                    Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-
-                    if (n == 3)
-                    {
-                        d.Dispose();
-
-                        sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
-                        {
-                            Assert.NotEqual(id, Environment.CurrentManagedThreadId);
-                            evt.Set();
-                        });
-                    }
-
-                    if (n > 3)
-                    {
-                        Assert.True(false);
-                    }
-
-                    return n + 1;
-                });
-
-                evt.WaitOne();
-            }
-        }
     }
 }
 #endif

+ 4 - 27
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Concurrency/SchedulerTest.cs

@@ -16,13 +16,6 @@ using Microsoft.Reactive.Testing;
 
 #if HAS_WINFORMS
 using System.Windows.Forms;
-using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler;
-using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler;
-#endif
-
-#if HAS_WPF
-using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler;
-using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler;
 #endif
 
 using System.Threading.Tasks;
@@ -34,14 +27,6 @@ namespace ReactiveTests.Tests
     [TestClass]
     public class SchedulerTest : ReactiveTest
     {
-#if HAS_DISPATCHER
-        [TestInitialize]
-        public void EnsureDispatcherAvailable()
-        {
-            _ = new System.Windows.DependencyObject();
-        }
-#endif
-
         #region IScheduler
 
         [TestMethod]
@@ -74,14 +59,10 @@ namespace ReactiveTests.Tests
             ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.CurrentThread.Schedule(TimeSpan.Zero, default(Action)));
             ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.CurrentThread.Schedule(DateTimeOffset.MaxValue, default(Action)));
 #if DESKTOPCLR
-            ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherScheduler.Current.Schedule(default(Action)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherScheduler.Current.ScheduleAction(new object(), default));
-            ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherScheduler.Current.Schedule(TimeSpan.Zero, default(Action)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherScheduler.Current.Schedule(DateTimeOffset.MaxValue, default(Action)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => LegacyDispatcherScheduler.Current.Schedule(default(Action)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => LegacyDispatcherScheduler.Current.ScheduleAction(new object(), default));
-            ReactiveAssert.Throws<ArgumentNullException>(() => LegacyDispatcherScheduler.Current.Schedule(TimeSpan.Zero, default(Action)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => LegacyDispatcherScheduler.Current.Schedule(DateTimeOffset.MaxValue, default(Action)));
+            ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherScheduler.Instance.Schedule(default(Action)));
+            ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherScheduler.Instance.ScheduleAction(new object(), default));
+            ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherScheduler.Instance.Schedule(TimeSpan.Zero, default(Action)));
+            ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherScheduler.Instance.Schedule(DateTimeOffset.MaxValue, default(Action)));
 #endif
             ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.Immediate.Schedule(default(Action)));
             ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.Immediate.ScheduleAction(new object(), default));
@@ -107,10 +88,6 @@ namespace ReactiveTests.Tests
             ReactiveAssert.Throws<ArgumentNullException>(() => new ControlScheduler(lbl).ScheduleAction(new object(), default(Action<object>)));
             ReactiveAssert.Throws<ArgumentNullException>(() => new ControlScheduler(lbl).Schedule(TimeSpan.Zero, default(Action)));
             ReactiveAssert.Throws<ArgumentNullException>(() => new ControlScheduler(lbl).Schedule(DateTimeOffset.MaxValue, default(Action)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => new LegacyControlScheduler(lbl).Schedule(default(Action)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => new LegacyControlScheduler(lbl).ScheduleAction(new object(), default(Action<object>)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => new LegacyControlScheduler(lbl).Schedule(TimeSpan.Zero, default(Action)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => new LegacyControlScheduler(lbl).Schedule(DateTimeOffset.MaxValue, default(Action)));
 #endif
             var ctx = new SynchronizationContext();
             ReactiveAssert.Throws<ArgumentNullException>(() => new SynchronizationContextScheduler(ctx).Schedule(default(Action)));

+ 2 - 0
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Internal/HalfSerializerTest.cs

@@ -14,7 +14,9 @@ namespace ReactiveTests.Tests
     [TestClass]
     public class HalfSerializerTest
     {
+#pragma warning disable IDE0044 // Spurious suggestion to add readonly. Not appropriate because this is passed by ref
         private int _wip;
+#pragma warning restore IDE0044
         private Exception _error;
         private readonly Consumer _consumer = new();
 

+ 6 - 120
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ObserveOnTest.cs

@@ -16,15 +16,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 #if HAS_DISPATCHER
 using System.Windows.Threading;
-
-using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler;
-using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler;
 #endif
 
 #if HAS_WINFORMS
 using System.Windows.Forms;
-using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler;
-using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler;
 #endif
 
 using Assert = Xunit.Assert;
@@ -45,11 +40,7 @@ namespace ReactiveTests.Tests
 #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overloads being tested.
             ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ObserveOn<int>(default(IObservable<int>), new ControlScheduler(new Label())));
             ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ObserveOn<int>(someObservable, default(ControlScheduler)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ObserveOn<int>(default(IObservable<int>), new LegacyControlScheduler(new Label())));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ObserveOn<int>(someObservable, default(LegacyControlScheduler)));
 
-            ReactiveAssert.Throws<ArgumentNullException>(() => WindowsFormsControlObservable.ObserveOnWindowsFormsControl<int>(default(IObservable<int>), new Label()));
-            ReactiveAssert.Throws<ArgumentNullException>(() => WindowsFormsControlObservable.ObserveOnWindowsFormsControl<int>(someObservable, default(Label)));
             ReactiveAssert.Throws<ArgumentNullException>(() => ControlObservable.ObserveOn<int>(default(IObservable<int>), new Label()));
             ReactiveAssert.Throws<ArgumentNullException>(() => ControlObservable.ObserveOn<int>(someObservable, default(Label)));
 #pragma warning restore IDE0034
@@ -59,12 +50,7 @@ namespace ReactiveTests.Tests
 #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overloads being tested.
             ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ObserveOn<int>(default(IObservable<int>), new DispatcherScheduler(Dispatcher.CurrentDispatcher)));
             ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ObserveOn<int>(someObservable, default(DispatcherScheduler)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ObserveOn<int>(default(IObservable<int>), new LegacyDispatcherScheduler(Dispatcher.CurrentDispatcher)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ObserveOn<int>(someObservable, default(LegacyDispatcherScheduler)));
 
-            ReactiveAssert.Throws<ArgumentNullException>(() => WpfDispatcherObservable.ObserveOnWpfDispatcher<int>(default(IObservable<int>), Dispatcher.CurrentDispatcher));
-            ReactiveAssert.Throws<ArgumentNullException>(() => WpfDispatcherObservable.ObserveOnWpfDispatcher<int>(someObservable, default(Dispatcher)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => WpfDispatcherObservable.ObserveOnCurrentWpfDispatcher<int>(default(IObservable<int>)));
             ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherObservable.ObserveOn<int>(default(IObservable<int>), Dispatcher.CurrentDispatcher));
             ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherObservable.ObserveOn<int>(someObservable, default(Dispatcher)));
             ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherObservable.ObserveOnDispatcher<int>(default(IObservable<int>)));
@@ -80,27 +66,6 @@ namespace ReactiveTests.Tests
         {
             var okay = true;
 
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt = new ManualResetEvent(false);
-
-                Observable.Range(0, 10, NewThreadScheduler.Default).ObserveOnWindowsFormsControl(lbl).Subscribe(x =>
-                {
-                    lbl.Text = x.ToString();
-                    okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext);
-                }, () => evt.Set());
-
-                evt.WaitOne();
-            }
-
-            Assert.True(okay);
-        }
-
-        [TestMethod]
-        public void ObserveOn_Control_Legacy()
-        {
-            var okay = true;
-
             using (WinFormsTestUtils.RunTest(out var lbl))
             {
                 var evt = new ManualResetEvent(false);
@@ -141,28 +106,7 @@ namespace ReactiveTests.Tests
 #if HAS_DISPATCHER
         [TestMethod]
         [Asynchronous]
-        public void ObserveOnDispatcher()
-        {
-            using (DispatcherHelpers.RunTest(out var dispatcher))
-            {
-                RunAsync(evt =>
-                {
-                    var okay = true;
-                    Observable.Range(0, 10, NewThreadScheduler.Default).ObserveOnWpfDispatcher(dispatcher).Subscribe(x =>
-                    {
-                        okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext);
-                    }, () =>
-                    {
-                        Assert.True(okay);
-                        evt.Set();
-                    });
-                });
-            }
-        }
-
-        [TestMethod]
-        [Asynchronous]
-        public void ObserveOn_Dispatcher_Legacy()
+        public void ObserveOn_Dispatcher()
         {
             using (DispatcherHelpers.RunTest(out var dispatcher))
             {
@@ -204,31 +148,7 @@ namespace ReactiveTests.Tests
 
         [TestMethod]
         [Asynchronous]
-        public void ObserveOnCurrentDispatcher()
-        {
-            using (DispatcherHelpers.RunTest(out var dispatcher))
-            {
-                RunAsync(evt =>
-                {
-                    var okay = true;
-                    dispatcher.BeginInvoke(new Action(() =>
-                    {
-                        Observable.Range(0, 10, NewThreadScheduler.Default).ObserveOnCurrentWpfDispatcher().Subscribe(x =>
-                        {
-                            okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext);
-                        }, () =>
-                        {
-                            Assert.True(okay);
-                            evt.Set();
-                        });
-                    }));
-                });
-            }
-        }
-
-        [TestMethod]
-        [Asynchronous]
-        public void ObserveOn_CurrentDispatcher_Legacy()
+        public void ObserveOn_CurrentDispatcher()
         {
             using (DispatcherHelpers.RunTest(out var dispatcher))
             {
@@ -240,7 +160,7 @@ namespace ReactiveTests.Tests
                         Observable.Range(0, 10, NewThreadScheduler.Default).ObserveOnDispatcher().Subscribe(x =>
                         {
                             okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext);
-                        }, () =>
+                        },  () =>
                         {
                             Assert.True(okay);
                             evt.Set();
@@ -250,43 +170,9 @@ namespace ReactiveTests.Tests
             }
         }
 
-
         [TestMethod]
         [Asynchronous]
-        public void ObserveOnCurrentDispatcher_Error()
-        {
-            using (DispatcherHelpers.RunTest(out var dispatcher))
-            {
-                RunAsync(evt =>
-                {
-                    var ex = new Exception();
-                    var okay = true;
-
-                    dispatcher.BeginInvoke(new Action(() =>
-                    {
-                        Observable.Throw<int>(ex).ObserveOnCurrentWpfDispatcher().Subscribe(x =>
-                        {
-                            okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext);
-                        },
-                        e =>
-                        {
-                            Assert.True(okay);
-                            Assert.Same(ex, e);
-                            evt.Set();
-                        },
-                        () =>
-                        {
-                            Assert.True(false);
-                            evt.Set();
-                        });
-                    }));
-                });
-            }
-        }
-
-        [TestMethod]
-        [Asynchronous]
-        public void ObserveOn_Error_Legacy()
+        public void ObserveOn_Error()
         {
             using (DispatcherHelpers.RunTest(out var dispatcher))
             {
@@ -776,8 +662,8 @@ namespace ReactiveTests.Tests
             Observable.Range(1, N)
                 .ObserveOn(scheduler)
                 .Subscribe(
-                    v => threads.Add(Environment.CurrentManagedThreadId), 
-                    e => cde.Signal(), 
+                    v => threads.Add(Environment.CurrentManagedThreadId),
+                    e => cde.Signal(),
                     () => cde.Signal()
                 );
 

+ 4 - 152
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/SubscribeOnTest.cs

@@ -15,14 +15,10 @@ using System.Windows.Threading;
 using System.Reactive;
 using System.Reactive.Subjects;
 
-using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler;
-using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler;
 #endif
 
 #if HAS_WINFORMS
 using System.Windows.Forms;
-using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler;
-using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler;
 #endif
 
 using Assert = Xunit.Assert;
@@ -44,11 +40,7 @@ namespace ReactiveTests.Tests
 #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested.
             ReactiveAssert.Throws<ArgumentNullException>(() => Observable.SubscribeOn<int>(default(IObservable<int>), new ControlScheduler(new Label())));
             ReactiveAssert.Throws<ArgumentNullException>(() => Observable.SubscribeOn<int>(someObservable, default(ControlScheduler)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Observable.SubscribeOn<int>(default(IObservable<int>), new LegacyControlScheduler(new Label())));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Observable.SubscribeOn<int>(someObservable, default(LegacyControlScheduler)));
 
-            ReactiveAssert.Throws<ArgumentNullException>(() => WindowsFormsControlObservable.SubscribeOnWindowFormsControl<int>(default(IObservable<int>), new Label()));
-            ReactiveAssert.Throws<ArgumentNullException>(() => WindowsFormsControlObservable.SubscribeOnWindowFormsControl<int>(someObservable, default(Label)));
             ReactiveAssert.Throws<ArgumentNullException>(() => ControlObservable.SubscribeOn<int>(default(IObservable<int>), new Label()));
             ReactiveAssert.Throws<ArgumentNullException>(() => ControlObservable.SubscribeOn<int>(someObservable, default(Label)));
 #pragma warning restore IDE0034
@@ -57,12 +49,7 @@ namespace ReactiveTests.Tests
 #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested.
             ReactiveAssert.Throws<ArgumentNullException>(() => Observable.SubscribeOn<int>(default(IObservable<int>), new DispatcherScheduler(Dispatcher.CurrentDispatcher)));
             ReactiveAssert.Throws<ArgumentNullException>(() => Observable.SubscribeOn<int>(someObservable, default(DispatcherScheduler)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Observable.SubscribeOn<int>(default(IObservable<int>), new LegacyDispatcherScheduler(Dispatcher.CurrentDispatcher)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Observable.SubscribeOn<int>(someObservable, default(LegacyDispatcherScheduler)));
 
-            ReactiveAssert.Throws<ArgumentNullException>(() => WpfDispatcherObservable.SubscribeOnWpfDispatcher<int>(default(IObservable<int>), Dispatcher.CurrentDispatcher));
-            ReactiveAssert.Throws<ArgumentNullException>(() => WpfDispatcherObservable.SubscribeOnWpfDispatcher<int>(someObservable, default(Dispatcher)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => WpfDispatcherObservable.SubscribeOnCurrentWpfDispatcher<int>(default(IObservable<int>)));
             ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherObservable.SubscribeOn<int>(default(IObservable<int>), Dispatcher.CurrentDispatcher));
             ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherObservable.SubscribeOn<int>(someObservable, default(Dispatcher)));
             ReactiveAssert.Throws<ArgumentNullException>(() => DispatcherObservable.SubscribeOnDispatcher<int>(default(IObservable<int>)));
@@ -74,7 +61,7 @@ namespace ReactiveTests.Tests
 
 #if HAS_WINFORMS
         [TestMethod]
-        public void SubscribeOn_Control_Legacy()
+        public void SubscribeOn_Control()
         {
             var okay = true;
 
@@ -96,40 +83,6 @@ namespace ReactiveTests.Tests
                     };
                 })
                 .SubscribeOn(lbl)
-                .Subscribe(_ => {});
-
-                evt2.WaitOne();
-                d.Dispose();
-
-                evt.WaitOne();
-            }
-
-            Assert.True(okay);
-        }
-
-        [TestMethod]
-        public void SubscribeOnControl()
-        {
-            var okay = true;
-
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt2 = new ManualResetEvent(false);
-                var evt = new ManualResetEvent(false);
-                var d = Observable.Create<int>(obs =>
-                {
-                    lbl.Text = "Subscribe";
-                    okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext);
-                    evt2.Set();
-
-                    return () =>
-                    {
-                        lbl.Text = "Unsubscribe";
-                        okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext);
-                        evt.Set();
-                    };
-                })
-                .SubscribeOnWindowFormsControl(lbl)
                 .Subscribe(_ => { });
 
                 evt2.WaitOne();
@@ -142,7 +95,7 @@ namespace ReactiveTests.Tests
         }
 
         [TestMethod]
-        public void SubscribeOn_ControlScheduler_Legacy()
+        public void SubscribeOn_ControlScheduler()
         {
             var okay = true;
 
@@ -175,47 +128,12 @@ namespace ReactiveTests.Tests
 
             Assert.True(okay);
         }
-
-        [TestMethod]
-        public void SubscribeOn_ControlScheduler()
-        {
-            var okay = true;
-
-            using (WinFormsTestUtils.RunTest(out var lbl))
-            {
-                var evt2 = new ManualResetEvent(false);
-                var evt = new ManualResetEvent(false);
-                
-                var d = Observable.Create<int>(obs =>
-                {
-                    lbl.Text = "Subscribe";
-                    okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext);
-                    evt2.Set();
-
-                    return () =>
-                    {
-                        lbl.Text = "Unsubscribe";
-                        okay &= (SynchronizationContext.Current is System.Windows.Forms.WindowsFormsSynchronizationContext);
-                        evt.Set();
-                    };
-                })
-                .SubscribeOn(new System.Reactive.WindowsForms.ControlScheduler(lbl))
-                .Subscribe(_ => { });
-
-                evt2.WaitOne();
-                d.Dispose();
-
-                evt.WaitOne();
-            }
-
-            Assert.True(okay);
-        }
 #endif
 
 #if HAS_DISPATCHER
         [TestMethod]
         [Asynchronous]
-        public void SubscribeOn_Dispatcher_Legacy()
+        public void SubscribeOn_Dispatcher()
         {
             using (DispatcherHelpers.RunTest(out var dispatcher))
             {
@@ -244,37 +162,6 @@ namespace ReactiveTests.Tests
             }
         }
 
-        [TestMethod]
-        [Asynchronous]
-        public void SubscribeOnDispatcher()
-        {
-            using (DispatcherHelpers.RunTest(out var dispatcher))
-            {
-                RunAsync(evt =>
-                {
-                    var s = new AsyncSubject<Unit>();
-                    var okay = true;
-                    var d = Observable.Create<int>(obs =>
-                    {
-                        okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext);
-                        s.OnNext(Unit.Default);
-                        s.OnCompleted();
-
-                        return () =>
-                        {
-                            okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext);
-                            Assert.True(okay);
-                            evt.Set();
-                        };
-                    })
-                    .SubscribeOnWpfDispatcher(dispatcher)
-                    .Subscribe(_ => { });
-
-                    s.Subscribe(_ => d.Dispose());
-                });
-            }
-        }
-
         [TestMethod]
         [Asynchronous]
         public void SubscribeOn_DispatcherScheduler()
@@ -308,7 +195,7 @@ namespace ReactiveTests.Tests
 
         [TestMethod]
         [Asynchronous]
-        public void SubscribeOn_CurrentDispatcher_Legacy()
+        public void SubscribeOn_CurrentDispatcher()
         {
             using (DispatcherHelpers.RunTest(out var dispatcher))
             {
@@ -340,41 +227,6 @@ namespace ReactiveTests.Tests
                 });
             }
         }
-
-        [TestMethod]
-        [Asynchronous]
-        public void SubscribeOnCurrentDispatcher()
-        {
-            using (DispatcherHelpers.RunTest(out var dispatcher))
-            {
-                RunAsync(evt =>
-                {
-                    var s = new AsyncSubject<Unit>();
-                    var okay = true;
-
-                    dispatcher.BeginInvoke(new Action(() =>
-                    {
-                        var d = Observable.Create<int>(obs =>
-                        {
-                            okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext);
-                            s.OnNext(Unit.Default);
-                            s.OnCompleted();
-
-                            return () =>
-                            {
-                                okay &= (SynchronizationContext.Current is System.Windows.Threading.DispatcherSynchronizationContext);
-                                Assert.True(okay);
-                                evt.Set();
-                            };
-                        })
-                        .SubscribeOnCurrentWpfDispatcher()
-                        .Subscribe(_ => { });
-
-                        s.Subscribe(_ => d.Dispose());
-                    }));
-                });
-            }
-        }
 #endif
 
         #endregion + TestBase +

+ 5 - 38
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/QbservableTest.cs

@@ -16,19 +16,11 @@ using System.Reactive.Subjects;
 using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Threading;
+
 using Microsoft.Reactive.Testing;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 using Assert = Xunit.Assert;
-#if HAS_WINFORMS
-using LegacyControlScheduler = System.Reactive.Concurrency.ControlScheduler;
-using ControlScheduler = System.Reactive.WindowsForms.ControlScheduler;
-#endif
-
-#if HAS_WPF
-using LegacyDispatcherScheduler = System.Reactive.Concurrency.DispatcherScheduler;
-using DispatcherScheduler = System.Reactive.Wpf.DispatcherScheduler;
-#endif
 
 namespace ReactiveTests.Tests
 {
@@ -39,14 +31,6 @@ namespace ReactiveTests.Tests
         private readonly IQbservable<int> _qbMy = new MyQbservable<int>();
         private readonly IQbservableProvider _qbp = new MyQbservableProvider();
 
-#if HAS_DISPATCHER
-        [TestInitialize]
-        public void EnsureDispatcherAvailable()
-        {
-            _ = new System.Windows.DependencyObject();
-        }
-#endif
-
         [TestMethod]
         public void LocalQueryMethodImplementationTypeAttribute()
         {
@@ -887,14 +871,12 @@ namespace ReactiveTests.Tests
 #endif
 #if HAS_WINFORMS
             ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.ObserveOn(_qbMy, default(ControlScheduler)));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.ObserveOn(_qbMy, default(LegacyControlScheduler)));
             ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.ObserveOn(_qbNull, new ControlScheduler(new System.Windows.Forms.Form())));
 #endif
             ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.ObserveOn(_qbNull, Scheduler.Immediate));
             ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.ObserveOn(_qbNull, new SynchronizationContext()));
 #if HAS_DISPATCHER
-            ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.ObserveOn(_qbNull, DispatcherScheduler.Current));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.ObserveOn(_qbNull, LegacyDispatcherScheduler.Current));
+            ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.ObserveOn(_qbNull, DispatcherScheduler.Instance));
 #endif
         }
 
@@ -904,8 +886,7 @@ namespace ReactiveTests.Tests
         {
             _qbMy.ObserveOn(Scheduler.Immediate);
             _qbMy.ObserveOn(new SynchronizationContext());
-            Qbservable.ObserveOn(_qbMy, DispatcherScheduler.Current);
-            Qbservable.ObserveOn(_qbMy, LegacyDispatcherScheduler.Current);
+            Qbservable.ObserveOn(_qbMy, DispatcherScheduler.Instance);
         }
 #endif
 
@@ -1178,8 +1159,7 @@ namespace ReactiveTests.Tests
             ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.SubscribeOn(_qbNull, Scheduler.Immediate));
             ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.SubscribeOn(_qbNull, new SynchronizationContext()));
 #if HAS_DISPATCHER
-            ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.SubscribeOn(_qbNull, DispatcherScheduler.Current));
-            ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.SubscribeOn(_qbNull, LegacyDispatcherScheduler.Current));
+            ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.SubscribeOn(_qbNull, DispatcherScheduler.Instance));
 #endif
 #if HAS_WINFORMS
             ReactiveAssert.Throws<ArgumentNullException>(() => Qbservable.SubscribeOn(_qbMy, default(ControlScheduler)));
@@ -1187,26 +1167,13 @@ namespace ReactiveTests.Tests
 #endif
         }
 
-        [TestMethod]
-        public void SubscribeOn_Legacy()
-        {
-            _qbMy.SubscribeOn(Scheduler.Immediate);
-            _qbMy.SubscribeOn(new SynchronizationContext());
-#if HAS_DISPATCHER
-            Qbservable.SubscribeOn(_qbMy, LegacyDispatcherScheduler.Current);
-#endif
-#if HAS_WINFORMS
-            _qbMy.SubscribeOn(new ControlScheduler(new System.Windows.Forms.Form()));
-#endif
-        }
-
         [TestMethod]
         public void SubscribeOn()
         {
             _qbMy.SubscribeOn(Scheduler.Immediate);
             _qbMy.SubscribeOn(new SynchronizationContext());
 #if HAS_DISPATCHER
-            Qbservable.SubscribeOn(_qbMy, DispatcherScheduler.Current);
+            Qbservable.SubscribeOn(_qbMy, DispatcherScheduler.Instance);
 #endif
 #if HAS_WINFORMS
             _qbMy.SubscribeOn(new ControlScheduler(new System.Windows.Forms.Form()));