Ok, so this is a bit longwinded, but it should have pretty good performance:
class OperatorUiResultListener : ResultListener
{
public enum EventType
{
StepStart,
StepCompleted
}
ConcurrentQueue<(TestStepRun, EventType)> workQueue = new ConcurrentQueue<(TestStepRun, EventType)>();
public override void Close()
{
while (workQueue.IsEmpty == false)
{
TapThread.Sleep(1);
}
base.Close();
System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Send,new Action(() =>
{
System.Windows.Media.CompositionTarget.Rendering -= CompositionTargetOnRendering;
}));
}
public override void Open()
{
base.Open();
System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Send,new Action(() =>
{
System.Windows.Media.CompositionTarget.Rendering += CompositionTargetOnRendering;
}));
}
void CompositionTargetOnRendering(object sender, EventArgs e)
{
List<(TestStepRun, EventType)> poppedElements = new List<(TestStepRun, EventType)>();
while (workQueue.TryDequeue(out var thing) && poppedElements.Count < 100)
{
for (int i = 0; i < poppedElements.Count; i++)
{
// if the step started and stopped before the UI got updated..
// just keep the last event.
if (poppedElements[i].Item1.Id == thing.Item1.Id)
{
poppedElements.RemoveAt(i);
break;
}
}
poppedElements.Add(thing);
}
foreach (var element in poppedElements)
{
// process events
if (element.Item2 == EventType.StepStart)
{
//var node = Plan.RootDescendents.FirstOrDefault(x => x.Id == e.TestStepRun.TestStepId);
//if (node is null) return;
//node.IsRunning = true;
//var viewModel = new StepRunDisplayTimerViewModel(e.TestStepRun, node);
//_runningSteps.Add(viewModel);
}
else
{
//var vm = _runningSteps.FirstOrDefault(x => x.StepRun.TestStepId == e.TestStepRun.TestStepId);
//vm?.StopTimer();
//vm.TestStepTreeNode.IsRunning = false;
//_runningSteps.Remove(vm);
}
}
}
public override void OnTestStepRunStart(TestStepRun stepRun)
{
base.OnTestStepRunStart(stepRun);
workQueue.Enqueue((stepRun, EventType.StepStart));
}
public override void OnTestStepRunCompleted(TestStepRun stepRun)
{
base.OnTestStepRunStart(stepRun);
workQueue.Enqueue((stepRun, EventType.StepCompleted));
}
}