Elapsed Time While Running Test Plan & Test Steps

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));
        }
    }
3 Likes