Inheritance: ICanExecute, ISequenceInstance2
        public EnumStateMachine <T> ForFromSubroutine(T state, Subroutine sub)
        {
            var seq = new Sequence(name: $"ForFromSubroutine({sub.Name})");

            seq.WhenExecuted.Execute(i =>
            {
                System.Threading.CancellationTokenSource cts;
                var evt     = new System.Threading.ManualResetEvent(false);
                var runTask = sub.Run(out cts);

                runTask.ContinueWith(t =>
                {
                    evt.Set();
                });

                System.Threading.WaitHandle.WaitAny(new System.Threading.WaitHandle[]
                {
                    evt, i.CancelToken.WaitHandle
                });

                log.Debug("Cancel 1");
                cts?.Cancel();

                if (!runTask.Wait(10000))
                {
                    this.log.Information("Sequence {0} failed to cancel in time", seq.Name);
                }
            });

            var seqJob = (seq.WhenExecuted as Sequence.SequenceJob);

            this.stateConfigs[state] = seqJob;

            return(this);
        }
示例#2
0
        private void WireupLifeCycle(Controller.Subroutine sub)
        {
            sub.Lifecycle.Subscribe(lc =>
            {
                switch (lc)
                {
                case Controller.Subroutine.LifeCycles.Running:
                case Controller.Subroutine.LifeCycles.RunningLoop:
                    // Check if we shouldn't run
                    if (this.requestedSub != this.currentSub)
                    {
                        this.currentSub?.RequestCancel();
                    }
                    break;

                case Controller.Subroutine.LifeCycles.Setup:
                    if (this.reportMasterStatus)
                    {
                        Executor.Current.LogMasterStatus(Name, true);
                    }
                    break;

                case Controller.Subroutine.LifeCycles.Stopped:
                    if (this.reportMasterStatus)
                    {
                        Executor.Current.LogMasterStatus(Name, false);
                    }

                    QueueCheckState();
                    break;
                }
            });
        }
示例#3
0
        public TriggeredSubBaseModule([System.Runtime.CompilerServices.CallerMemberName] string name = "", bool reportMasterStatus = true)
            : base(name)
        {
            this.reportMasterStatus = reportMasterStatus;

            this.stateChecker = Observer.NotifyOn(Observer.Create <bool>(_ =>
            {
                if (this.transition)
                {
                    if (this.currentSub != null)
                    {
                        this.currentSub.RequestCancel();
                        Executor.Current.Cancel(this.currentSub);
                    }

                    // Transition done, let's exit and check again
                    this.transition = false;
                    this.currentSub = null;
                    QueueCheckState();
                    return;
                }

                if (this.currentSub != this.requestedSub)
                {
                    if (this.requestedSub == null)
                    {
                        // Request to turn off
                        this.transition = true;
                        QueueCheckState();
                        return;
                    }
                    else
                    {
                        var sub         = this.requestedSub;
                        this.currentSub = sub;
                        Executor.Current.Execute(sub);
                        QueueCheckState();
                    }
                }
            }), this.scheduler);

            WireupLifeCycle(this.powerOffSub);
            WireupLifeCycle(this.powerOnSub);

            OutputTrigger.Subscribe(x =>
            {
                if (x.Trigger)
                {
                    this.requestedSub = (x.Power || AlwaysUsePowerOnSub) ? this.powerOnSub : this.powerOffSub;
                }
                else
                {
                    this.requestedSub = null;
                }

                QueueCheckState();
            });
        }
示例#4
0
        public DmxPlayback([System.Runtime.CompilerServices.CallerMemberName] string name = "")
        {
            this.name = name;
            this.sub = new Subroutine("SUB_" + this.name);
            this.watch = new Stopwatch();
            this.pixelMapping = new Dictionary<int, int[]>();
            long timestampOffset = 0;

            this.sub.RunAction(ins =>
            {
                var bitmap = (Bitmap)this.device.GetFrameBuffer(this.sub.Token, this.device)[DataElements.PixelBitmap];
                if (bitmap.Width != this.pixelWidth || bitmap.Height != this.pixelHeight)
                    throw new ArgumentException("Invalid bitmap size");

                var bitmapRect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);

                int bytesPerPixel = Bitmap.GetPixelFormatSize(bitmap.PixelFormat) / 8;
                int stride = 4 * ((bitmap.Width * bytesPerPixel + 3) / 4);
                int byteCount = stride * bitmap.Height;
                this.rgbValues = new byte[byteCount];

                do
                {
                    // See if we should restart
                    if (this.file.Position >= this.file.Length)
                    {
                        // Restart
                        this.file.Position = 0;
                        this.dmxFrame = null;
                        this.watch.Reset();
                    }

                    if (this.dmxFrame == null)
                    {
                        this.dmxFrame = ReadFrame(this.binRead);
                        timestampOffset = this.dmxFrame.TimestampMS;
                    }

                    this.watch.Start();

                    while (!ins.IsCancellationRequested && this.file.Position < this.file.Length)
                    {
                        // Calculate when the next stop is
                        this.nextStop = this.dmxFrame.TimestampMS - timestampOffset;

                        long msLeft = this.nextStop - this.watch.ElapsedMilliseconds;
                        if (msLeft <= 0)
                        {
                            // Output
                            OutputData(this.dmxFrame, bitmap, bitmapRect, stride);

                            // Read next frame
                            this.dmxFrame = ReadFrame(this.binRead);
                            continue;
                        }
                        else if (msLeft < 16)
                        {
                            SpinWait.SpinUntil(() => this.watch.ElapsedMilliseconds >= this.nextStop);
                            continue;
                        }

                        Thread.Sleep(1);
                    }
                } while (!ins.IsCancellationRequested && this.loop);

                this.watch.Stop();
            });
        }