Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions TUnit.Core/Executors/DedicatedThreadExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ namespace TUnit.Core;

public class DedicatedThreadExecutor : GenericAbstractExecutor, ITestRegisteredEventReceiver
{
protected sealed override async ValueTask ExecuteAsync(Func<ValueTask> action)
protected sealed override ValueTask ExecuteAsync(Func<ValueTask> action)
{
// On browser platforms, threading is not supported, so fall back to direct execution
#if NET5_0_OR_GREATER
if (OperatingSystem.IsBrowser())
{
await action();
return;
return action();
}
#endif

Expand Down Expand Up @@ -56,7 +55,7 @@ protected sealed override async ValueTask ExecuteAsync(Func<ValueTask> action)
ConfigureThread(thread);
thread.Start(state);

await tcs.Task;
return new ValueTask(tcs.Task);
}

private void ExecuteAsyncActionWithMessagePump(Func<ValueTask> action, TaskCompletionSource<object?> tcs)
Expand All @@ -74,17 +73,16 @@ private void ExecuteAsyncActionWithMessagePump(Func<ValueTask> action, TaskCompl
workAvailableEvent = new ManualResetEventSlim(false);
#endif
var taskScheduler = new DedicatedThreadTaskScheduler(Thread.CurrentThread, workAvailableEvent);
var dedicatedContext = new DedicatedThreadSynchronizationContext(taskScheduler, workAvailableEvent);
var dedicatedContext = new DedicatedThreadSynchronizationContext(workAvailableEvent);

SynchronizationContext.SetSynchronizationContext(dedicatedContext);

try
{
var task = Task.Factory.StartNew(static async action =>
{
// Inside this task, TaskScheduler.Current will be our scheduler
await ((Func<ValueTask>)action!)();
}, action, CancellationToken.None, TaskCreationOptions.None, taskScheduler).Unwrap();
var task = Task.Factory.StartNew(
static action => ((Func<ValueTask>)action!)().AsTask(),
action, CancellationToken.None, TaskCreationOptions.None, taskScheduler)
.Unwrap();

// Try fast path first - many tests complete quickly
// Use IsCompleted to avoid synchronous wait
Expand Down Expand Up @@ -297,15 +295,13 @@ public bool ProcessPendingTasks()
internal sealed class DedicatedThreadSynchronizationContext : SynchronizationContext
{
private readonly Thread _dedicatedThread;
private readonly DedicatedThreadTaskScheduler _taskScheduler;
private readonly ManualResetEventSlim? _workAvailableEvent;
private readonly Queue<(SendOrPostCallback callback, object? state)> _workQueue = new();
private readonly Lock _queueLock = new();

public DedicatedThreadSynchronizationContext(DedicatedThreadTaskScheduler taskScheduler, ManualResetEventSlim? workAvailableEvent)
public DedicatedThreadSynchronizationContext(ManualResetEventSlim? workAvailableEvent)
{
_dedicatedThread = Thread.CurrentThread;
_taskScheduler = taskScheduler;
_workAvailableEvent = workAvailableEvent;
}

Expand Down
Loading