From 345cb0a05eb8e72022ea56a4cf0008041f9f8a7c Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Tue, 4 Feb 2025 12:19:32 -0800 Subject: [PATCH 1/4] Update ActionDebouncer.cs --- src/DynamoCoreWpf/Utilities/ActionDebouncer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs b/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs index c1c89a3e2f6..6b218cfc2d7 100644 --- a/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs +++ b/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs @@ -26,7 +26,7 @@ public void Cancel() /// /// Delays the "action" for a "timeout" number of milliseconds - /// The input Action will run on same syncronization context as the Debounce method call. + /// The input Action will run on same syncronization context as the Debounce method call (or the thread pool if a sync context does not exist, ex. in non UI tests). /// /// Number of milliseconds to wait /// The action to execute after the timeout runs out. @@ -36,6 +36,11 @@ public void Debounce(int timeout, Action action) Cancel(); cts = new CancellationTokenSource(); + // The TaskScheduler.FromCurrentSynchronizationContext() exists only if there is a valid SyncronizationContex. + // Calling this method from a non UI thread could have a null SyncronizationContex.Current, + // so in that case we use the default TaskScheduler which uses the thread pool. + var taskScheduler = SynchronizationContext.Current != null ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default; + Task.Delay(timeout, cts.Token).ContinueWith((t) => { try @@ -50,7 +55,7 @@ public void Debounce(int timeout, Action action) logger?.Log("Failed to run debounce action with the following error:"); logger?.Log(ex.ToString()); } - }, TaskScheduler.FromCurrentSynchronizationContext()); + }, taskScheduler); } public void Dispose() From c7c8a36f73ee766a57d39e8ba306a8714a555b3f Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 5 Feb 2025 05:13:32 -0800 Subject: [PATCH 2/4] Update ActionDebouncer.cs --- src/DynamoCoreWpf/Utilities/ActionDebouncer.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs b/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs index 6b218cfc2d7..5d2d630d728 100644 --- a/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs +++ b/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs @@ -2,6 +2,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using System.Windows.Threading; namespace Dynamo.Wpf.Utilities { @@ -39,7 +40,19 @@ public void Debounce(int timeout, Action action) // The TaskScheduler.FromCurrentSynchronizationContext() exists only if there is a valid SyncronizationContex. // Calling this method from a non UI thread could have a null SyncronizationContex.Current, // so in that case we use the default TaskScheduler which uses the thread pool. - var taskScheduler = SynchronizationContext.Current != null ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Default; + TaskScheduler taskScheduler = null; + if (SynchronizationContext.Current != null) + {// This should always be the case in UI threads. + taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); + } + else + {// This might happen when running tests in non UI threads. + if (Dispatcher.CurrentDispatcher != null) + {// UI thread. + logger?.LogError("The UI thread does not seem to have a SyncronizationContext."); + } + taskScheduler = TaskScheduler.Default; + } Task.Delay(timeout, cts.Token).ContinueWith((t) => { From db2671d5889e4e0b5aeb0e333337d62cb728a6b8 Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Wed, 5 Feb 2025 13:07:59 -0800 Subject: [PATCH 3/4] Update ActionDebouncer.cs --- src/DynamoCoreWpf/Utilities/ActionDebouncer.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs b/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs index 5d2d630d728..969ea171df2 100644 --- a/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs +++ b/src/DynamoCoreWpf/Utilities/ActionDebouncer.cs @@ -2,7 +2,6 @@ using System; using System.Threading; using System.Threading.Tasks; -using System.Windows.Threading; namespace Dynamo.Wpf.Utilities { @@ -46,8 +45,10 @@ public void Debounce(int timeout, Action action) taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); } else - {// This might happen when running tests in non UI threads. - if (Dispatcher.CurrentDispatcher != null) + { + // This might happen when running tests in non UI threads. + // But if we are in a UI thread, then log this as a potential error. + if (System.Windows.Application.Current?.Dispatcher?.Thread == Thread.CurrentThread) {// UI thread. logger?.LogError("The UI thread does not seem to have a SyncronizationContext."); } From f63d3edec0c237385ee0e04017a07c48b7a2202d Mon Sep 17 00:00:00 2001 From: pinzart90 Date: Thu, 6 Feb 2025 13:34:26 -0800 Subject: [PATCH 4/4] update --- test/DynamoCoreWpfTests/DynamoTestUIBase.cs | 18 +++++++++--------- test/DynamoCoreWpfTests/RecordedTests.cs | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/DynamoCoreWpfTests/DynamoTestUIBase.cs b/test/DynamoCoreWpfTests/DynamoTestUIBase.cs index 42d90b227d3..6b7385bfc4a 100644 --- a/test/DynamoCoreWpfTests/DynamoTestUIBase.cs +++ b/test/DynamoCoreWpfTests/DynamoTestUIBase.cs @@ -59,7 +59,7 @@ private void PrettyPrint(object obj) Console.WriteLine("}"); } - internal void SetupStartupDiagnostics() + internal void StartupDiagnostics() { System.Console.WriteLine($"PID {Process.GetCurrentProcess().Id} Start test: {TestContext.CurrentContext.Test.Name}"); TestUtilities.WebView2Tag = TestContext.CurrentContext.Test.Name; @@ -69,16 +69,16 @@ internal void SetupStartupDiagnostics() Dispatcher.CurrentDispatcher.Hooks.OperationPosted += Hooks_OperationPosted; } - internal void SetupBeforeCleanupDiagnostics() + internal void BeforeCleanupDiagnostics() { - Dispatcher.CurrentDispatcher.Hooks.OperationPosted -= Hooks_OperationPosted; if (!SkipDispatcherFlush) { DispatcherUtil.DoEventsLoop(() => DispatcherOpsCounter == 0); } + Dispatcher.CurrentDispatcher.Hooks.OperationPosted -= Hooks_OperationPosted; } - internal void SetupAfterCleanupDiagnostics() + internal void AfterCleanupDiagnostics() { TestUtilities.WebView2Tag = string.Empty; using (var currentProc = Process.GetCurrentProcess()) @@ -93,10 +93,10 @@ internal void SetupAfterCleanupDiagnostics() } } - internal void SetupCleanupDiagnostics() + internal void CleanupDiagnostics() { - SetupBeforeCleanupDiagnostics(); - SetupAfterCleanupDiagnostics(); + BeforeCleanupDiagnostics(); + AfterCleanupDiagnostics(); } } @@ -132,7 +132,7 @@ protected string ExecutingDirectory [SetUp] public virtual void Start() { - testDiagnostics.SetupStartupDiagnostics(); + testDiagnostics.StartupDiagnostics(); var assemblyPath = Assembly.GetExecutingAssembly().Location; preloader = new Preloader(Path.GetDirectoryName(assemblyPath)); preloader.Preload(); @@ -229,7 +229,7 @@ public void Exit() { Console.WriteLine(ex.StackTrace); } - testDiagnostics.SetupAfterCleanupDiagnostics(); + testDiagnostics.AfterCleanupDiagnostics(); } protected virtual void GetLibrariesToPreload(List libraries) diff --git a/test/DynamoCoreWpfTests/RecordedTests.cs b/test/DynamoCoreWpfTests/RecordedTests.cs index b328e5ead93..875881b1cf3 100644 --- a/test/DynamoCoreWpfTests/RecordedTests.cs +++ b/test/DynamoCoreWpfTests/RecordedTests.cs @@ -54,7 +54,7 @@ public class RecordedUnitTestBase : DynamoViewModelUnitTest public override void Setup() { - testDiagnostics.SetupStartupDiagnostics(); + testDiagnostics.StartupDiagnostics(); base.Setup(); // Fixed seed randomizer for predictability. @@ -63,10 +63,10 @@ public override void Setup() public override void Cleanup() { - testDiagnostics.SetupBeforeCleanupDiagnostics(); + testDiagnostics.BeforeCleanupDiagnostics(); commandCallback = null; base.Cleanup(); - testDiagnostics.SetupAfterCleanupDiagnostics(); + testDiagnostics.AfterCleanupDiagnostics(); } #endregion