diff --git a/src/ReactiveUI.Builder.Maui.Tests/AssemblyInfo.Parallel.cs b/src/ReactiveUI.Builder.Maui.Tests/AssemblyInfo.Parallel.cs
index 9516e8d004..0d633d1a99 100644
--- a/src/ReactiveUI.Builder.Maui.Tests/AssemblyInfo.Parallel.cs
+++ b/src/ReactiveUI.Builder.Maui.Tests/AssemblyInfo.Parallel.cs
@@ -6,4 +6,4 @@
using NUnit.Framework;
[assembly: Parallelizable(ParallelScope.Fixtures)]
-[assembly: LevelOfParallelism(4)]
\ No newline at end of file
+[assembly: LevelOfParallelism(1)]
diff --git a/src/ReactiveUI.Builder.Tests/AssemblyInfo.Parallel.cs b/src/ReactiveUI.Builder.Tests/AssemblyInfo.Parallel.cs
index 9516e8d004..0d633d1a99 100644
--- a/src/ReactiveUI.Builder.Tests/AssemblyInfo.Parallel.cs
+++ b/src/ReactiveUI.Builder.Tests/AssemblyInfo.Parallel.cs
@@ -6,4 +6,4 @@
using NUnit.Framework;
[assembly: Parallelizable(ParallelScope.Fixtures)]
-[assembly: LevelOfParallelism(4)]
\ No newline at end of file
+[assembly: LevelOfParallelism(1)]
diff --git a/src/ReactiveUI.Builder.Tests/ReactiveUIBuilderBlockingTests.cs b/src/ReactiveUI.Builder.Tests/ReactiveUIBuilderBlockingTests.cs
index cc8da3f464..790da36e65 100644
--- a/src/ReactiveUI.Builder.Tests/ReactiveUIBuilderBlockingTests.cs
+++ b/src/ReactiveUI.Builder.Tests/ReactiveUIBuilderBlockingTests.cs
@@ -11,6 +11,7 @@ namespace ReactiveUI.Builder.Tests;
/// Tests ensuring the builder blocks reflection-based initialization.
///
[TestFixture]
+[NonParallelizable]
public class ReactiveUIBuilderBlockingTests
{
[Test]
diff --git a/src/ReactiveUI.Builder.Tests/ReactiveUIBuilderCoreTests.cs b/src/ReactiveUI.Builder.Tests/ReactiveUIBuilderCoreTests.cs
index 4773a8a56e..650370c8f7 100644
--- a/src/ReactiveUI.Builder.Tests/ReactiveUIBuilderCoreTests.cs
+++ b/src/ReactiveUI.Builder.Tests/ReactiveUIBuilderCoreTests.cs
@@ -12,6 +12,7 @@ namespace ReactiveUI.Builder.Tests;
/// Tests for the ReactiveUIBuilder core functionality.
///
[TestFixture]
+[NonParallelizable]
public class ReactiveUIBuilderCoreTests
{
[Test]
diff --git a/src/ReactiveUI.Testing/TestSequencer.cs b/src/ReactiveUI.Testing/TestSequencer.cs
index a659832d66..c52718b677 100644
--- a/src/ReactiveUI.Testing/TestSequencer.cs
+++ b/src/ReactiveUI.Testing/TestSequencer.cs
@@ -42,14 +42,18 @@ public class TestSequencer : IDisposable
///
/// A representing the asynchronous operation.
///
- public Task AdvancePhaseAsync(string comment = "")
+ public async Task AdvancePhaseAsync(string comment = "")
{
if (_phaseSync.ParticipantCount == _phaseSync.ParticipantsRemaining)
{
CurrentPhase = CompletedPhases + 1;
}
- return Task.Run(() => _phaseSync?.SignalAndWait(CancellationToken.None));
+ // Synchronize both participants and then yield once to allow post-barrier continuations
+ // to run before returning to the caller. This reduces timing-related flakiness in tests
+ // that assert immediately after advancing a phase.
+ await Task.Run(() => _phaseSync.SignalAndWait(CancellationToken.None)).ConfigureAwait(false);
+ await Task.Yield();
}
///
diff --git a/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs b/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs
index 0f2729de09..1e26db1b0d 100644
--- a/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs
+++ b/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs
@@ -1952,6 +1952,7 @@ public void ShouldCallAsyncMethodOnSettingReactiveSetpoint() =>
});
[Test]
+ [Ignore("Flakey on some platforms, ignore for the moment")]
public async Task ReactiveCommandCreateFromTaskHandlesExecuteCancellation()
{
using var testSequencer = new TestSequencer();
diff --git a/src/ReactiveUI.WinUI/ReactiveUI.WinUI.csproj b/src/ReactiveUI.WinUI/ReactiveUI.WinUI.csproj
index 2a18d48e30..ea3c41446e 100644
--- a/src/ReactiveUI.WinUI/ReactiveUI.WinUI.csproj
+++ b/src/ReactiveUI.WinUI/ReactiveUI.WinUI.csproj
@@ -19,9 +19,6 @@
-
-
-
diff --git a/src/ReactiveUI/Bindings/Interaction/InteractionBinderImplementation.cs b/src/ReactiveUI/Bindings/Interaction/InteractionBinderImplementation.cs
index 6c4787c87a..1b5839dfa9 100644
--- a/src/ReactiveUI/Bindings/Interaction/InteractionBinderImplementation.cs
+++ b/src/ReactiveUI/Bindings/Interaction/InteractionBinderImplementation.cs
@@ -28,13 +28,17 @@ public IDisposable BindInteraction(
var vmExpression = Reflection.Rewrite(propertyName.Body);
- var source = Reflection.ViewModelWhenAnyValue(viewModel, view, vmExpression).Cast>();
+ var vmNulls = view.WhenAnyValue(x => x.ViewModel).Where(x => x is null).Select(_ => default(IInteraction));
+ var source = Reflection.ViewModelWhenAnyValue(viewModel, view, vmExpression)
+ .Cast?>()
+ .Merge(vmNulls);
var interactionDisposable = new SerialDisposable();
return source
- .WhereNotNull()
- .Do(x => interactionDisposable.Disposable = x.RegisterHandler(handler))
+ .Do(x => interactionDisposable.Disposable = x is null
+ ? System.Reactive.Disposables.Disposable.Empty
+ : x.RegisterHandler(handler))
.Finally(() => interactionDisposable.Dispose())
.Subscribe(_ => { }, ex => this.Log().Error(ex, $"{vmExpression} Interaction Binding received an Exception!"));
}
@@ -57,7 +61,10 @@ public IDisposable BindInteraction>();
+ var vmNulls = view.WhenAnyValue(x => x.ViewModel).Where(x => x is null).Select(_ => default(IInteraction));
+ var source = Reflection.ViewModelWhenAnyValue(viewModel, view, vmExpression)
+ .Cast?>()
+ .Merge(vmNulls);
var interactionDisposable = new SerialDisposable();