Skip to content

Commit ebee018

Browse files
pinzart90pinzart
andauthoredFeb 10, 2025··
Update ActionDebouncer.cs to support tests with no Sync context (#15804)
Co-authored-by: Tiberiu Pinzariu <[email protected]>
1 parent 3614b13 commit ebee018

File tree

3 files changed

+32
-18
lines changed

3 files changed

+32
-18
lines changed
 

‎src/DynamoCoreWpf/Utilities/ActionDebouncer.cs

+21-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public void Cancel()
2626

2727
/// <summary>
2828
/// Delays the "action" for a "timeout" number of milliseconds
29-
/// The input Action will run on same syncronization context as the Debounce method call.
29+
/// 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).
3030
/// </summary>
3131
/// <param name="timeout">Number of milliseconds to wait</param>
3232
/// <param name="action">The action to execute after the timeout runs out.</param>
@@ -36,6 +36,25 @@ public void Debounce(int timeout, Action action)
3636
Cancel();
3737
cts = new CancellationTokenSource();
3838

39+
// The TaskScheduler.FromCurrentSynchronizationContext() exists only if there is a valid SyncronizationContex.
40+
// Calling this method from a non UI thread could have a null SyncronizationContex.Current,
41+
// so in that case we use the default TaskScheduler which uses the thread pool.
42+
TaskScheduler taskScheduler = null;
43+
if (SynchronizationContext.Current != null)
44+
{// This should always be the case in UI threads.
45+
taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
46+
}
47+
else
48+
{
49+
// This might happen when running tests in non UI threads.
50+
// But if we are in a UI thread, then log this as a potential error.
51+
if (System.Windows.Application.Current?.Dispatcher?.Thread == Thread.CurrentThread)
52+
{// UI thread.
53+
logger?.LogError("The UI thread does not seem to have a SyncronizationContext.");
54+
}
55+
taskScheduler = TaskScheduler.Default;
56+
}
57+
3958
Task.Delay(timeout, cts.Token).ContinueWith((t) =>
4059
{
4160
try
@@ -50,7 +69,7 @@ public void Debounce(int timeout, Action action)
5069
logger?.Log("Failed to run debounce action with the following error:");
5170
logger?.Log(ex.ToString());
5271
}
53-
}, TaskScheduler.FromCurrentSynchronizationContext());
72+
}, taskScheduler);
5473
}
5574

5675
public void Dispose()

‎test/DynamoCoreWpfTests/DynamoTestUIBase.cs

+8-8
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private void PrettyPrint(object obj)
5959
Console.WriteLine("}");
6060
}
6161

62-
internal void SetupStartupDiagnostics()
62+
internal void StartupDiagnostics()
6363
{
6464
System.Console.WriteLine($"PID {Process.GetCurrentProcess().Id} Start test: {TestContext.CurrentContext.Test.Name}");
6565
TestUtilities.WebView2Tag = TestContext.CurrentContext.Test.Name;
@@ -69,7 +69,7 @@ internal void SetupStartupDiagnostics()
6969
Dispatcher.CurrentDispatcher.Hooks.OperationPosted += Hooks_OperationPosted;
7070
}
7171

72-
internal void SetupBeforeCleanupDiagnostics()
72+
internal void BeforeCleanupDiagnostics()
7373
{
7474
Dispatcher.CurrentDispatcher.Hooks.OperationPosted -= Hooks_OperationPosted;
7575
if (!SkipDispatcherFlush)
@@ -78,7 +78,7 @@ internal void SetupBeforeCleanupDiagnostics()
7878
}
7979
}
8080

81-
internal void SetupAfterCleanupDiagnostics()
81+
internal void AfterCleanupDiagnostics()
8282
{
8383
TestUtilities.WebView2Tag = string.Empty;
8484
using (var currentProc = Process.GetCurrentProcess())
@@ -93,10 +93,10 @@ internal void SetupAfterCleanupDiagnostics()
9393
}
9494
}
9595

96-
internal void SetupCleanupDiagnostics()
96+
internal void CleanupDiagnostics()
9797
{
98-
SetupBeforeCleanupDiagnostics();
99-
SetupAfterCleanupDiagnostics();
98+
BeforeCleanupDiagnostics();
99+
AfterCleanupDiagnostics();
100100
}
101101
}
102102

@@ -132,7 +132,7 @@ protected string ExecutingDirectory
132132
[SetUp]
133133
public virtual void Start()
134134
{
135-
testDiagnostics.SetupStartupDiagnostics();
135+
testDiagnostics.StartupDiagnostics();
136136
var assemblyPath = Assembly.GetExecutingAssembly().Location;
137137
preloader = new Preloader(Path.GetDirectoryName(assemblyPath));
138138
preloader.Preload();
@@ -229,7 +229,7 @@ public void Exit()
229229
{
230230
Console.WriteLine(ex.StackTrace);
231231
}
232-
testDiagnostics.SetupAfterCleanupDiagnostics();
232+
testDiagnostics.AfterCleanupDiagnostics();
233233
}
234234

235235
protected virtual void GetLibrariesToPreload(List<string> libraries)

‎test/DynamoCoreWpfTests/RecordedTests.cs

+3-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
5-
using System.Reflection;
65
using System.Xml;
76
using System.Threading;
87
using CoreNodeModels.Input;
@@ -24,10 +23,6 @@
2423
using ProtoCore;
2524
using PythonNodeModels;
2625
using SystemTestServices;
27-
using System.Windows.Threading;
28-
using DynamoCoreWpfTests.Utility;
29-
using System.Diagnostics;
30-
using System.Threading.Tasks;
3126

3227
namespace DynamoCoreWpfTests
3328
{
@@ -54,7 +49,7 @@ public class RecordedUnitTestBase : DynamoViewModelUnitTest
5449

5550
public override void Setup()
5651
{
57-
testDiagnostics.SetupStartupDiagnostics();
52+
testDiagnostics.StartupDiagnostics();
5853

5954
base.Setup();
6055
// Fixed seed randomizer for predictability.
@@ -63,10 +58,10 @@ public override void Setup()
6358

6459
public override void Cleanup()
6560
{
66-
testDiagnostics.SetupBeforeCleanupDiagnostics();
61+
testDiagnostics.BeforeCleanupDiagnostics();
6762
commandCallback = null;
6863
base.Cleanup();
69-
testDiagnostics.SetupAfterCleanupDiagnostics();
64+
testDiagnostics.AfterCleanupDiagnostics();
7065
}
7166

7267
#endregion

0 commit comments

Comments
 (0)