TestWorker
A TestWorker pulls work items from a queue
and executes them.
using System;
using System.Runtime.CompilerServices;
using System.Threading;
namespace NUnit.Framework.Internal.Execution
{
[NullableContext(1)]
[Nullable(0)]
public class TestWorker
{
[NullableContext(0)]
public delegate void TestWorkerEventHandler (TestWorker worker, WorkItem work);
private static readonly Logger Log = InternalTrace.GetLogger("TestWorker");
[Nullable(2)]
private Thread _workerThread;
private int _workItemCount;
private bool _running;
[Nullable(2)]
private WorkItem _currentWorkItem;
private readonly object _cancelLock = new object();
public WorkItemQueue WorkQueue { get; }
public string Name { get; }
public bool IsAlive => _workerThread?.IsAlive ?? false;
[Nullable(2)]
[method: NullableContext(2)]
[field: Nullable(2)]
public event TestWorkerEventHandler Busy;
[Nullable(2)]
[method: NullableContext(2)]
[field: Nullable(2)]
public event TestWorkerEventHandler Idle;
public TestWorker(WorkItemQueue queue, string name)
{
Guard.ArgumentNotNull(queue, "queue");
WorkQueue = queue;
Name = name;
}
private void TestWorkerThreadProc()
{
_running = true;
try {
while (_running) {
_currentWorkItem = WorkQueue.Dequeue();
if (_currentWorkItem == null)
break;
Log.Info("{0} executing {1}", Thread.CurrentThread.Name, _currentWorkItem.Name);
_currentWorkItem.TestWorker = this;
this.Busy?.Invoke(this, _currentWorkItem);
_currentWorkItem.Execute();
this.Idle?.Invoke(this, _currentWorkItem);
_workItemCount++;
}
} finally {
Log.Info("{0} stopping - {1} WorkItems processed.", Name, _workItemCount);
}
}
public void Start()
{
_workerThread = new Thread(TestWorkerThreadProc) {
Name = Name
};
if (OperatingSystem.IsWindows())
_workerThread.SetApartmentState(WorkQueue.TargetApartment);
Log.Info("{0} starting on thread [{1}]", Name, _workerThread.ManagedThreadId);
_workerThread.Start();
}
public void Cancel(bool force)
{
if (force)
_running = false;
lock (_cancelLock) {
if (_workerThread != null && _currentWorkItem != null) {
_currentWorkItem.Cancel(force);
if (force)
_currentWorkItem = null;
}
}
}
}
}