コード例 #1
0
        /// <summary>
        /// Execute scenario in other thread
        /// </summary>
        /// <param name="param"></param>
        /// <param name="cancelToken"></param>
        public virtual void ExecuteAsyncParallel(ScenarioActionSource source, string param, ExecutionContext parentContext)
        {
            CheckRights(source, parentContext);

            TaskUtils.StartLongRunning(() =>
            {
                CheckValue(param, parentContext);
                var output = new OutputChangedDelegates();
                ExecutionContext context;
                var oldVal = GetPreviousValue();
                if (parentContext != null)
                {
                    var cancellationTokenSource = new SafeCancellationToken();
                    parentContext.CancellationTokenSource.RegisterCallback(cancellationTokenSource.Cancel);
                    context = new ExecutionContext(this, param, oldVal, output, parentContext, cancellationTokenSource);
                }
                else
                {
                    context = new ExecutionContext(this, param, oldVal, output, new SafeCancellationToken());
                }
                CheckContext(context);
                HandleExecution(() => ExecuteInternal(context));
            },
                                       HandleSet);
        }
コード例 #2
0
        protected ExecutionContext PrepareExecutionContext(string param, ExecutionContext parentContext)
        {
            var output = new OutputChangedDelegates();

            output.Add(val => SetCurrentValue(val, SystemActionSource));
            var tokenSource = PrepareCancellationTokenSource();
            ExecutionContext context;
            var prevValue = GetCurrentValue();

            if (parentContext == null)
            {
                context = new ExecutionContext(this, param, prevValue, output, tokenSource);
            }
            else
            {
                context = new ExecutionContext(this, param, prevValue, output, parentContext, tokenSource);
                parentContext.CancellationTokenSource.RegisterCallback(tokenSource.Cancel);
                CheckContext(context);
            }
            return(context);
        }
コード例 #3
0
        protected override void RunInternal()
        {
            if (GetScenario() == null)
            {
                return;
            }

            //удаляем старую подписку, если имеется
            if (_lastSubscribe != null)
            {
                GetScenario().RemoveOnStateChanged(_lastSubscribe);
            }

            //выполнение по подписке на изменение значения
            var executeBySubscription = true;

            //если сценарий это одиночное действие и нельзя подписаться на изменение целевого действия
            //то не выполняем по подписке, а выполняем просто через цикл
            if (GetScenario() is SingleActionScenario singleActionScen && !singleActionScen.ActionHolder.Action.IsSupportsEvent)
            {
                executeBySubscription = false;
            }

            var contextCancellationToken = new SafeCancellationToken();

            CancellationToken.RegisterCallback(contextCancellationToken.Cancel);
            if (executeBySubscription)
            {
                _lastSubscribe = (sender, args) =>
                {
                    if (CancellationToken.IsCancellationRequested)
                    {
                        //crutch; scenario can be changed before initializing, then we need to remove
                        //current subscribe from previous scenario. CancellationToken.IsCancellationRequested
                        //can be setted in true only when trigger stopped;
                        args.Value.Scenario.RemoveOnStateChanged(_lastSubscribe);
                    }
                    else
                    {
                        if (!args.Value.OnlyIntent)
                        {
                            var action        = TargetAction;
                            var outputChanged = new OutputChangedDelegates();
                            outputChanged.Add((value) => GetScenario().SetCurrentValue(value, ExecuteActionSource));
                            contextCancellationToken.Cancel();
                            contextCancellationToken = new SafeCancellationToken();
                            var executionContext = new ExecutionContext(this, args.Value.Value, args.Value.PreviousValue, outputChanged, contextCancellationToken);
                            TaskUtils.StartLongRunning(
                                () => action.SetValue(executionContext, string.Empty),
                                (exception) => Log.ErrorFormat(exception, "Ошибка выполнения триггера [{0}][{1}]", Name, Id));
                        }
                    }
                };
                GetScenario().SetOnStateChanged(_lastSubscribe);
            }
            else
            {
                var lastVal = string.Empty;
                var timerCancellationToken = SystemUtils.StartTimer(
                    (token) =>
                {
                    try
                    {
                        var curVal = GetScenario().CalculateCurrentValue(ViewActionSource, null);
                        if (!lastVal.Equals(curVal))
                        {
                            var prevVal = GetScenario().GetPreviousValue();
                            lastVal     = curVal;
                            contextCancellationToken.Cancel();
                            contextCancellationToken = new SafeCancellationToken();
                            var executionContext     = new ExecutionContext(this, curVal, prevVal, new OutputChangedDelegates(), contextCancellationToken);
                            try
                            {
                                TargetAction.SetValue(executionContext, string.Empty);
                            }
                            catch (Exception exception)
                            {
                                Log.ErrorFormat(exception, "Ошибка выполнения триггера [{0}][{1}]", Name, Id);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log.ErrorFormat(e, "Ошибка выполнения триггера [{0}][{1}]", Name, Id);
                    }
                },
                    () => TriggerChangesListenInterval,
                    true,
                    ticksSuperposition: true /*наложение тиков*/);
                CancellationToken.RegisterCallback(timerCancellationToken.Cancel);
            }
        }