Example #1
0
            private static Cell <T> Calm <T>(Cell <T> a)
            {
                Lazy <T>           initA  = a.SampleLazy();
                Lazy <IMaybe <T> > mInitA = initA.Map(Maybe.Just);

                return(Calm(Operational.Updates(a), mInitA).HoldLazy(initA));
            }
Example #2
0
        public FrView(Window window, Fridget fr, IListener l)
        {
            StreamSink <MouseEvent> sMouse = new StreamSink <MouseEvent>();
            StreamSink <KeyEvent>   sKey   = new StreamSink <KeyEvent>();

            this.MouseDown += (sender, args) => sMouse.Send(new MouseEvent(args, () => args.GetPosition(this)));
            this.MouseUp   += (sender, args) => sMouse.Send(new MouseEvent(args, () => args.GetPosition(this)));
            this.MouseMove += (sender, args) => sMouse.Send(new MouseEvent(args, () => args.GetPosition(this)));
            CellSink <IMaybe <Size> > size = new CellSink <IMaybe <Size> >(Maybe.Nothing <Size>());

            this.SizeChanged += (sender, args) => size.Send(Maybe.Just(args.NewSize));
            window.KeyDown   += (sender, args) =>
            {
                Key key = args.Key == Key.System ? args.SystemKey : args.Key;
                if (key == Key.Back)
                {
                    sKey.Send(new BackspaceKeyEvent());
                }
            };
            window.TextInput += (sender, args) => sKey.Send(new StringKeyEvent(args.Text));
            CellLoop <long> focus = new CellLoop <long>();

            Fridget.Output fo = fr.Reify(size, sMouse, sKey, focus, new Supply());
            focus.Loop(fo.SChangeFocus.Hold(-1));
            this.drawable = fo.Drawable;
            this.l        = new ImmutableCompositeListener(new[] { l, Operational.Updates(this.drawable).Listen(d => this.InvalidateVisual()) });
        }
Example #3
0
        public void TestUpdates()
        {
            BehaviorSink <int> b    = Behavior.CreateSink(9);
            List <int>         @out = new List <int>();
            IListener          l    = Operational.Updates(b).Listen(@out.Add);

            b.Send(2);
            b.Send(7);
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 2, 7 }, @out);
        }
Example #4
0
        public void TestUpdates()
        {
            CellSink <int> c    = Cell.CreateSink(9);
            List <int>     @out = new List <int>();
            IListener      l    = Operational.Updates(c).Listen(@out.Add);

            c.Send(2);
            c.Send(7);
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 2, 7 }, @out);
        }
Example #5
0
        public void TestHoldUpdates()
        {
            StreamSink <int>   s    = Stream.CreateSink <int>();
            DiscreteCell <int> c    = s.Hold(0);
            List <int>         @out = new List <int>();
            IListener          l    = Operational.Updates(c.Cell).Listen(@out.Add);

            s.Send(2);
            s.Send(9);
            l.Unlisten();
            CollectionAssert.AreEqual(new[] { 2, 9 }, @out);
        }
Example #6
0
        public void Test_Updates_TestCase()
        {
            Tuple <Stream <char>, Dictionary <int, Action> > st = MkStream(new Dictionary <int, char> {
                { 1, 'b' }, { 3, 'c' }
            });
            Stream <char>            s  = st.Item1;
            Dictionary <int, Action> sf = st.Item2;
            DiscreteCell <char>      c  = s.Hold('a');
            List <char> @out            = RunSimulation <char>(Operational.Updates(c.Cell).Listen, new[] { sf });

            CollectionAssert.AreEqual(new[] { 'b', 'c' }, @out);
        }
Example #7
0
        public void TestUpdates()
        {
            CellSink <int> c    = new CellSink <int>(9);
            List <int>     @out = new List <int>();

            using (Operational.Updates(c).Listen(@out.Add))
            {
                c.Send(2);
                c.Send(7);
            }
            CollectionAssert.AreEqual(new[] { 2, 7 }, @out);
        }
Example #8
0
        public void TestHoldUpdates()
        {
            StreamSink <int> s    = new StreamSink <int>();
            Cell <int>       c    = s.Hold(0);
            List <int>       @out = new List <int>();

            using (Operational.Updates(c).Listen(@out.Add))
            {
                s.Send(2);
                s.Send(9);
            }
            CollectionAssert.AreEqual(new[] { 2, 9 }, @out);
        }
Example #9
0
        public SLabel(Cell <string> text)
        {
            Action <string> setText = t => this.Dispatcher.InvokeIfNecessary(() => this.Text = t);

            // Set the initial value at the end of the transaction so it works with CellLoops.
            Transaction.Post(() => setText(text.Sample()));

            // ReSharper disable once UseObjectOrCollectionInitializer
            List <IListener> listeners = new List <IListener>();

            listeners.Add(Operational.Updates(text).Listen(setText));

            this.listeners = listeners;
        }
Example #10
0
        public STextBox(Stream <string> setText, string initText, Cell <bool> enabled)
        {
            base.Text = initText;

            List <IListener> listeners = new List <IListener>();

            StreamSink <int> sDecrement = new StreamSink <int>();
            Cell <bool>      allow      = setText.Map(_ => 1).OrElse(sDecrement).Accum(0, (b, d) => b + d).Map(b => b == 0);

            StreamSink <string> sUserChanges = new StreamSink <string>();

            this.SUserChanges = sUserChanges;
            this.Text         = sUserChanges.Gate(allow).OrElse(setText).Hold(initText);

            TextChangedEventHandler textChangedEventHandler = (sender, args) =>
            {
                string text = base.Text;
                this.Dispatcher.InvokeAsync(() => sUserChanges.Send(text));
            };

            this.TextChanged += textChangedEventHandler;

            // Set the initial value at the end of the transaction so it works with CellLoops.
            Transaction.Post(() => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = enabled.Sample()));

            listeners.Add(setText.Listen(t =>
            {
                this.Dispatcher.InvokeAsync(() =>
                {
                    this.TextChanged -= textChangedEventHandler;
                    base.Text         = t;
                    this.TextChanged += textChangedEventHandler;
                    sDecrement.Send(-1);
                });
            }));

            listeners.Add(Operational.Updates(enabled).Listen(e => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = e)));

            this.disposeListeners = () =>
            {
                foreach (IListener l in listeners)
                {
                    using (l)
                    {
                    }
                }
            };
        }
Example #11
0
        public void FunctionalBehaviorLoop()
        {
            BehaviorSink <int> s      = Behavior.CreateSink(0);
            Behavior <int>     result = Behavior.Loop <int>().WithoutCaptures(l => Operational.Updates(s).Snapshot(l, (n, o) => n + o).Hold(0).AsBehavior());

            List <int> @out = new List <int>();

            using (Transaction.Run(() => Operational.Value(result).Listen(@out.Add)))
            {
                s.Send(1);
                s.Send(2);
                s.Send(3);
            }

            CollectionAssert.AreEqual(new[] { 0, 1, 3, 6 }, @out);
        }
Example #12
0
        public SButton(Cell <bool> enabled)
        {
            StreamSink <Unit> sClickedSink = new StreamSink <Unit>();

            this.SClicked = sClickedSink;
            this.Click   += (sender, args) => sClickedSink.Send(Unit.Value);

            // Set the initial value at the end of the transaction so it works with CellLoops.
            Transaction.Post(() => this.IsEnabled = enabled.Sample());

            // ReSharper disable once UseObjectOrCollectionInitializer
            List <IListener> listeners = new List <IListener>();

            listeners.Add(Operational.Updates(enabled).Listen(e => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = e)));
            this.listeners = listeners;
        }
Example #13
0
        public void TestMapWithSwitchC()
        {
            IReadOnlyList <Test> list1 = new[] { new Test(0), new Test(1), new Test(2), new Test(3), new Test(4) };
            IReadOnlyList <Test> list2 = new[] { new Test(5), new Test(6), new Test(7), new Test(8), new Test(9) };

            CellSink <IReadOnlyList <Test> > v = Cell.CreateSink(list1);

            Cell <IReadOnlyList <int> > c = v.Map(oo => oo.Select(o => o.Value).Lift()).Map(o => o).SwitchC();

            List <IReadOnlyList <int> > streamOutput = new List <IReadOnlyList <int> >();
            IListener l = Operational.Updates(c).Listen(streamOutput.Add);

            List <IReadOnlyList <int> > cellOutput = new List <IReadOnlyList <int> >();
            IListener l2 = Transaction.Run(() => Operational.Value(c).Listen(cellOutput.Add));

            list1[2].Value.Send(12);
            list2[1].Value.Send(16);
            list1[4].Value.Send(14);
            Transaction.RunVoid(() =>
            {
                list2[2].Value.Send(17);
                list1[0].Value.Send(10);
                v.Send(list2);
            });
            list1[3].Value.Send(13);
            list2[3].Value.Send(18);

            l2.Unlisten();
            l.Unlisten();

            Assert.AreEqual(4, streamOutput.Count);
            Assert.AreEqual(5, cellOutput.Count);

            CollectionAssert.AreEqual(new[] { 0, 1, 2, 3, 4 }, cellOutput[0]);
            CollectionAssert.AreEqual(new[] { 0, 1, 12, 3, 4 }, streamOutput[0]);
            CollectionAssert.AreEqual(new[] { 0, 1, 12, 3, 4 }, cellOutput[1]);
            CollectionAssert.AreEqual(new[] { 0, 1, 12, 3, 14 }, streamOutput[1]);
            CollectionAssert.AreEqual(new[] { 0, 1, 12, 3, 14 }, cellOutput[2]);
            CollectionAssert.AreEqual(new[] { 5, 16, 17, 8, 9 }, streamOutput[2]);
            CollectionAssert.AreEqual(new[] { 5, 16, 17, 8, 9 }, cellOutput[3]);
            CollectionAssert.AreEqual(new[] { 5, 16, 17, 18, 9 }, streamOutput[3]);
            CollectionAssert.AreEqual(new[] { 5, 16, 17, 18, 9 }, cellOutput[4]);
        }
Example #14
0
        public void ImperativeBehaviorLoop()
        {
            BehaviorSink <int> s      = Behavior.CreateSink(0);
            Behavior <int>     result = Transaction.Run(
                () =>
            {
                BehaviorLoop <int> l       = new BehaviorLoop <int>();
                Behavior <int> resultLocal = Operational.Updates(s).Snapshot(l, (n, o) => n + o).Hold(0).AsBehavior();
                l.Loop(resultLocal);
                return(resultLocal);
            });

            List <int> @out = new List <int>();

            using (Transaction.Run(() => Operational.Value(result).Listen(@out.Add)))
            {
                s.Send(1);
                s.Send(2);
                s.Send(3);
            }

            CollectionAssert.AreEqual(new[] { 0, 1, 3, 6 }, @out);
        }
Example #15
0
        public void ImperativeBehaviorLoopFailsWhenLoopedInSeparateTransaction()
        {
            InvalidOperationException actual = null;

            BehaviorLoop <int> l = null;

            new Thread(
                () =>
                Transaction.RunVoid(
                    () =>
            {
                l = new BehaviorLoop <int>();
                Thread.Sleep(500);
            })).Start();

            try
            {
                BehaviorSink <int> s = Behavior.CreateSink(0);
                Transaction.RunVoid(
                    () =>
                {
                    Thread.Sleep(250);
                    Behavior <int> resultLocal = Operational.Updates(s).Snapshot(l, (n, o) => n + o).Hold(0).AsBehavior();
                    l.Loop(resultLocal);
                });
            }
            catch (InvalidOperationException e)
            {
                actual = e;
            }

            Thread.Sleep(500);

            Assert.IsNotNull(actual);
            Assert.AreEqual("Loop must be looped in the same transaction that it was created in.", actual.Message);
        }
Example #16
0
        public void ImperativeBehaviorLoopFailsWhenLoopedTwice()
        {
            InvalidOperationException actual = null;

            try
            {
                BehaviorSink <int> s = Behavior.CreateSink(0);
                Transaction.RunVoid(
                    () =>
                {
                    BehaviorLoop <int> l       = new BehaviorLoop <int>();
                    Behavior <int> resultLocal = Operational.Updates(s).Snapshot(l, (n, o) => n + o).Hold(0).AsBehavior();
                    l.Loop(resultLocal);
                    l.Loop(resultLocal);
                });
            }
            catch (InvalidOperationException e)
            {
                actual = e;
            }

            Assert.IsNotNull(actual);
            Assert.AreEqual("Loop was looped more than once.", actual.Message);
        }
Example #17
0
        public void FunctionalBehaviorLoopWithCaptures()
        {
            BehaviorSink <int> s = Behavior.CreateSink(0);

            (Behavior <int> result, Behavior <int> s2) = Behavior.Loop <int>()
                                                         .WithCaptures(l => (Behavior: Operational.Updates(s).Snapshot(l, (n, o) => n + o).Hold(0).AsBehavior(), Captures: s.Map(v => 2 * v)));

            List <int> @out = new List <int>();
            List <int> out2 = new List <int>();

            using (Transaction.Run(() => Operational.Value(result).Listen(@out.Add)))
                using (Transaction.Run(() => Operational.Value(s2).Listen(out2.Add)))

                {
                    s.Send(1);
                    s.Send(2);
                    s.Send(3);
                }

            CollectionAssert.AreEqual(new[] { 0, 1, 3, 6 }, @out);
            CollectionAssert.AreEqual(new[] { 0, 2, 4, 6 }, out2);
        }
Example #18
0
        public static Cell <Signal> Integrate(Cell <Signal> sig, double initial)
        {
            Stream <Signal> sSig = Operational.Updates(sig);

            return(sSig.Accum(sig.Sample().Integrate(initial), (n, o) => n.Integrate(o.ValueAt(n.T0))));
        }
            public Implementation(PetrolPumpWindow petrolPump)
            {
                SComboBox <IPump> logic = new SComboBox <IPump>(
                    new IPump[]
                {
                    new LifeCyclePump(),
                    new AccumulatePulsesPump(),
                    new ShowDollarsPump(),
                    new ClearSalePump(),
                    new KeypadPump(),
                    new PresetAmountPump()
                },
                    p => p.GetType().FullName);

                petrolPump.LogicComboBoxPlaceholder.Children.Add(logic);

                STextField textPrice1 = new STextField("2.149")
                {
                    Width = 100
                };

                petrolPump.Price1Placeholder.Children.Add(textPrice1);

                STextField textPrice2 = new STextField("2.341")
                {
                    Width = 100
                };

                petrolPump.Price2Placeholder.Children.Add(textPrice2);

                STextField textPrice3 = new STextField("1.499")
                {
                    Width = 100
                };

                petrolPump.Price3Placeholder.Children.Add(textPrice3);

                Func <string, double> parseDoubleSafe = s =>
                {
                    double n;
                    if (double.TryParse(s, out n))
                    {
                        return(n);
                    }

                    return(0.0);
                };

                StreamSink <Key> sKey = new StreamSink <Key>();
                Dictionary <Key, FrameworkElement> containersByKey = new Dictionary <Key, FrameworkElement>
                {
                    { Key.One, petrolPump.Keypad1Button },
                    { Key.Two, petrolPump.Keypad2Button },
                    { Key.Three, petrolPump.Keypad3Button },
                    { Key.Four, petrolPump.Keypad4Button },
                    { Key.Five, petrolPump.Keypad5Button },
                    { Key.Six, petrolPump.Keypad6Button },
                    { Key.Seven, petrolPump.Keypad7Button },
                    { Key.Eight, petrolPump.Keypad8Button },
                    { Key.Nine, petrolPump.Keypad9Button },
                    { Key.Zero, petrolPump.Keypad0Button },
                    { Key.Clear, petrolPump.KeypadClearButton }
                };

                foreach (KeyValuePair <Key, FrameworkElement> containerAndKey in containersByKey)
                {
                    containerAndKey.Value.MouseDown += async(sender, args) =>
                    {
                        if (args.LeftButton == MouseButtonState.Pressed)
                        {
                            await Task.Run(() => sKey.Send(containerAndKey.Key));
                        }
                    };
                }

                CellLoop <UpDown> nozzle1 = new CellLoop <UpDown>();
                CellLoop <UpDown> nozzle2 = new CellLoop <UpDown>();
                CellLoop <UpDown> nozzle3 = new CellLoop <UpDown>();

                Cell <double>             calibration = Cell.Constant(0.001);
                Cell <double>             price1      = textPrice1.Text.Map(parseDoubleSafe);
                Cell <double>             price2      = textPrice2.Text.Map(parseDoubleSafe);
                Cell <double>             price3      = textPrice3.Text.Map(parseDoubleSafe);
                CellSink <Stream <Unit> > csClearSale = new CellSink <Stream <Unit> >(Sodium.Stream.Never <Unit>());
                Stream <Unit>             sClearSale  = csClearSale.SwitchS();

                StreamSink <int> sFuelPulses = new StreamSink <int>();
                Cell <Outputs>   outputs     = logic.SelectedItem.Map(
                    pump => pump.Create(new Inputs(
                                            Operational.Updates(nozzle1),
                                            Operational.Updates(nozzle2),
                                            Operational.Updates(nozzle3),
                                            sKey,
                                            sFuelPulses,
                                            calibration,
                                            price1,
                                            price2,
                                            price3,
                                            sClearSale)));

                Cell <Delivery> delivery        = outputs.Map(o => o.Delivery).SwitchC();
                Cell <string>   presetLcd       = outputs.Map(o => o.PresetLcd).SwitchC();
                Cell <string>   saleCostLcd     = outputs.Map(o => o.SaleCostLcd).SwitchC();
                Cell <string>   saleQuantityLcd = outputs.Map(o => o.SaleQuantityLcd).SwitchC();
                Cell <string>   priceLcd1       = outputs.Map(o => o.PriceLcd1).SwitchC();
                Cell <string>   priceLcd2       = outputs.Map(o => o.PriceLcd2).SwitchC();
                Cell <string>   priceLcd3       = outputs.Map(o => o.PriceLcd3).SwitchC();
                Stream <Unit>   sBeep           = outputs.Map(o => o.SBeep).SwitchS();
                Stream <Sale>   sSaleComplete   = outputs.Map(o => o.SSaleComplete).SwitchS();

                SoundPlayer beepPlayer = new SoundPlayer(GetResourceStream(@"sounds\beep.wav"));

                this.listeners.Add(sBeep.Listen(_ => new Thread(() => beepPlayer.PlaySync())
                {
                    IsBackground = true
                }.Start()));

                SoundPlayer fastRumblePlayer = new SoundPlayer(GetResourceStream(@"sounds\fast.wav"));
                Action      stopFast         = () => { };
                Action      playFast         = () =>
                {
                    ManualResetEvent mre = new ManualResetEvent(false);
                    new Thread(() =>
                    {
                        fastRumblePlayer.PlayLooping();
                        mre.WaitOne();
                        fastRumblePlayer.Stop();
                    })
                    {
                        IsBackground = true
                    }.Start();
                    stopFast = () => mre.Set();
                };

                SoundPlayer slowRumblePlayer = new SoundPlayer(GetResourceStream(@"sounds\slow.wav"));
                Action      stopSlow         = () => { };
                Action      playSlow         = () =>
                {
                    ManualResetEvent mre = new ManualResetEvent(false);
                    new Thread(() =>
                    {
                        slowRumblePlayer.PlayLooping();
                        mre.WaitOne();
                        slowRumblePlayer.Stop();
                    })
                    {
                        IsBackground = true
                    }.Start();
                    stopSlow = () => mre.Set();
                };

                this.listeners.Add(delivery.Changes().Listen(d =>
                {
                    petrolPump.Dispatcher.InvokeIfNecessary(() =>
                    {
                        if (d == Delivery.Fast1 || d == Delivery.Fast2 || d == Delivery.Fast3)
                        {
                            playFast();
                        }
                        else
                        {
                            stopFast();
                        }

                        if (d == Delivery.Slow1 || d == Delivery.Slow2 || d == Delivery.Slow3)
                        {
                            playSlow();
                        }
                        else
                        {
                            stopSlow();
                        }
                    });
                }));

                StackPanel presetLcdStackPanel = new StackPanel {
                    Orientation = Orientation.Horizontal
                };

                petrolPump.PresetPlaceholder.Children.Add(presetLcdStackPanel);
                this.listeners.Add(presetLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(presetLcdStackPanel, t, 5, true))));

                StackPanel saleCostStackPanel = new StackPanel {
                    Orientation = Orientation.Horizontal
                };

                petrolPump.DollarsPlaceholder.Children.Add(saleCostStackPanel);
                this.listeners.Add(saleCostLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(saleCostStackPanel, t, 5, true))));

                StackPanel saleQuantityLcdStackPanel = new StackPanel {
                    Orientation = Orientation.Horizontal
                };

                petrolPump.LitersPlaceholder.Children.Add(saleQuantityLcdStackPanel);
                this.listeners.Add(saleQuantityLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(saleQuantityLcdStackPanel, t, 5, true))));

                StackPanel priceLcd1StackPanel = new StackPanel {
                    Orientation = Orientation.Horizontal
                };

                petrolPump.Fuel1Placeholder.Children.Add(priceLcd1StackPanel);
                this.listeners.Add(priceLcd1.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd1StackPanel, t, 5, false))));

                StackPanel priceLcd2StackPanel = new StackPanel {
                    Orientation = Orientation.Horizontal
                };

                petrolPump.Fuel2Placeholder.Children.Add(priceLcd2StackPanel);
                this.listeners.Add(priceLcd2.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd2StackPanel, t, 5, false))));

                StackPanel priceLcd3StackPanel = new StackPanel {
                    Orientation = Orientation.Horizontal
                };

                petrolPump.Fuel3Placeholder.Children.Add(priceLcd3StackPanel);
                this.listeners.Add(priceLcd3.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd3StackPanel, t, 5, false))));

                Dictionary <CellLoop <UpDown>, Image> nozzles = new Dictionary <CellLoop <UpDown>, Image>
                {
                    { nozzle1, petrolPump.Nozzle1Image },
                    { nozzle2, petrolPump.Nozzle2Image },
                    { nozzle3, petrolPump.Nozzle3Image }
                };

                this.listeners.AddRange(nozzles.Select(nozzle => nozzle.Key.Listen(p => petrolPump.Dispatcher.InvokeIfNecessary(() => nozzle.Value.Margin = p == UpDown.Up ? new Thickness(0, 0, 0, 0) : new Thickness(0, 30, 0, 0)))));

                foreach (KeyValuePair <CellLoop <UpDown>, Image> nozzle in nozzles)
                {
                    StreamSink <Unit> nozzleClicks = new StreamSink <Unit>();
                    nozzle.Value.MouseDown += async(sender, args) =>
                    {
                        if (args.LeftButton == MouseButtonState.Pressed)
                        {
                            await Task.Run(() => nozzleClicks.Send(Unit.Value));
                        }
                    };
                    nozzle.Key.Loop(nozzleClicks.Snapshot(nozzle.Key, (_, n) => n == UpDown.Down ? UpDown.Up : UpDown.Down).Hold(UpDown.Down));
                }

                this.listeners.Add(sSaleComplete.Listen(sale =>
                {
                    Task.Run(() =>
                    {
                        petrolPump.Dispatcher.InvokeIfNecessary(() =>
                        {
                            SaleCompleteDialog dialog = new SaleCompleteDialog(
                                sale.Fuel.ToString(),
                                Formatters.FormatPrice(sale.Price, null),
                                Formatters.FormatSaleCost(sale.Cost),
                                Formatters.FormatSaleQuantity(sale.Quantity));
                            dialog.Owner = petrolPump;
                            csClearSale.Send(dialog.SOkClicked);
                            dialog.Show();
                            IListener l = null;
                            // ReSharper disable once RedundantAssignment
                            l = dialog.SOkClicked.Listen(_ =>
                            {
                                petrolPump.Dispatcher.InvokeIfNecessary(() => dialog.Close());

                                // ReSharper disable once AccessToModifiedClosure
                                using (l)
                                {
                                }
                            });
                        });
                    });
                }));

                Task.Run(async() =>
                {
                    while (true)
                    {
                        Transaction.RunVoid(() =>
                        {
                            switch (delivery.Sample())
                            {
                            case Delivery.Fast1:
                            case Delivery.Fast2:
                            case Delivery.Fast3:
                                sFuelPulses.Send(40);
                                break;

                            case Delivery.Slow1:
                            case Delivery.Slow2:
                            case Delivery.Slow3:
                                sFuelPulses.Send(2);
                                break;
                            }
                        });

                        await Task.Delay(200).ConfigureAwait(false);
                    }
                    // ReSharper disable once FunctionNeverReturns
                });
            }