private void PlayMacroAction(PlayableMacroAction playableMacroAction)
        {
            ControlPanel.ApplyMacroActionState(playableMacroAction.Macro.ID, playableMacroAction.MacroAction.ID, MacroActionState.Ongoing);
            if (playableMacroAction.MacroAction.Type == MacroActionType.Wait)
            {
                MacroWaitAction macroWaitAction = (MacroWaitAction)playableMacroAction.MacroAction;
                switch (macroWaitAction.WaitForEvent)
                {
                case MacroActionWaitForEvent.Timeout:
                {
                    Thread.Sleep(macroWaitAction.TimeoutMilliseconds);
                }
                break;

                case MacroActionWaitForEvent.PreviousActionsCompleted:
                {
                    List <PlayableMacroAction> previousPlayableMacroActions = new List <PlayableMacroAction>();
                    MacroPlaybackContainer     container = _macroPlaybackContainers[playableMacroAction.Macro.ID];
                    foreach (PlayableMacroAction previousPlayableMacroAction in container.PlayableMacroActions.TakeWhile(x => x.MacroAction.ID != playableMacroAction.MacroAction.ID))
                    {
                        if (previousPlayableMacroAction.MacroAction.Type == MacroActionType.Wait)
                        {
                            previousPlayableMacroActions.Clear();
                        }
                        else
                        {
                            previousPlayableMacroActions.Add(previousPlayableMacroAction);
                        }
                    }
                    WaitWhileOngoing(previousPlayableMacroActions);
                }
                break;
                }
                ControlPanel.ApplyMacroActionState(playableMacroAction.Macro.ID, playableMacroAction.MacroAction.ID, MacroActionState.Success);
            }
            else
            {
                bool actionSuccess = ControlPanel.TakeAction(playableMacroAction.Action);
                lock (_macroPlaybackContainers)
                {
                    playableMacroAction.MacroActionState = !actionSuccess
                                                ? MacroActionState.Failure
                                                : playableMacroAction.MacroAction.Type == MacroActionType.Start || playableMacroAction.MacroAction.Type == MacroActionType.Stop || playableMacroAction.MacroAction.Type == MacroActionType.Restart
                                                        ? MacroActionState.Success
                                                        : MacroActionState.Ongoing;
                }
                ControlPanel.ApplyMacroActionState(playableMacroAction.Macro.ID, playableMacroAction.MacroAction.ID, playableMacroAction.MacroActionState);
            }
        }
        private void PlayThread(Macro macro, List <IMacroAction> macroActions)
        {
            lock (_macroPlaybackContainers)
            {
                if (_macroPlaybackContainers.ContainsKey(macro.ID))
                {
                    return;
                }

                _macroPlaybackContainers.Add(macro.ID, null);
            }

            macroActions.ForEach(macroAction => ControlPanel.ApplyMacroActionState(macro.ID, macroAction.ID, MacroActionState.Unknown));

            List <PlayableMacroAction> playableMacroActions = macroActions.Select(macroAction =>
            {
                if (macroAction.Type == MacroActionType.Wait)
                {
                    return(new PlayableMacroAction(macro, macroAction));
                }

                IAction action = CreateAction(macroAction);
                return(action != null ? new PlayableMacroAction(macro, macroAction, action) : null);
            }).Where(x => x != null).ToList();

            MacroPlaybackContainer container = new MacroPlaybackContainer(macro, playableMacroActions);

            lock (_macroPlaybackContainers)
                _macroPlaybackContainers[macro.ID] = container;

            container.PlayableMacroActions.ForEach(PlayMacroAction);

            WaitWhileOngoing(container.PlayableMacroActions);

            lock (_macroPlaybackContainers)
                _macroPlaybackContainers.Remove(macro.ID);
        }