public void TestInvocationBehaviourIgnore()
        {
            OcDispatcher dispatcher = new OcDispatcher();

            dispatcher.NewInvocationBehaviour = NewInvocationBehaviour.Cancel;
            bool called = false;

            dispatcher.Invoke(() => { called = true; });
            dispatcher.Invoke(s => { called = true; }, new object());
            dispatcher.InvokeAsync(() => { called = true; });
            dispatcher.InvokeAsync(s => { called = true; }, new object());

            dispatcher.Invoke(() => { called = true; return(0); });
            dispatcher.Invoke(s => { called = true; return(0); }, new object());
            dispatcher.InvokeAsync(() => { called = true; return(0); });
            dispatcher.InvokeAsync(s => { called = true; return(0); }, new object());

            dispatcher.InvokeAsyncAwaitable(() => { called = true; });
            dispatcher.InvokeAsyncAwaitable(s => { called = true; }, new object());
            dispatcher.InvokeAsyncAwaitable(() => { called = true; return(0); });
            dispatcher.InvokeAsyncAwaitable(s => { called = true; return(0); }, new object());


            dispatcher.NewInvocationBehaviour = NewInvocationBehaviour.Accept;
            dispatcher.Pass();

            Assert.IsFalse(called);
            dispatcher.Dispose();
        }
        public void DisposeTest()
        {
            OcDispatcher         dispatcher = new OcDispatcher();
            ManualResetEventSlim mre        = new ManualResetEventSlim(false);
            bool invoked1 = false;
            bool invoked2 = false;
            bool freezed  = false;
            InvocationResult <bool> invocationResult  = null;
            InvocationResult <bool> invocationResult1 = null;

            dispatcher.InvokeAsync(() =>
            {
                dispatcher.InvokeAsync(() =>
                {
                    freezed = true;
                    mre.Wait();
                });


                invocationResult = dispatcher.Invoke(() => invoked1 = true);
            });

            Thread thread = new Thread(
                () =>
            {
                while (!freezed)
                {
                }

                invocationResult1 = dispatcher.Invoke(() => invoked2 = true);
            });

            thread.Start();

            ManualResetEventSlim mreDisposed = new ManualResetEventSlim(false);

            dispatcher.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == nameof(OcDispatcher.Status) &&
                    dispatcher.Status == OcDispatcherStatus.Disposed)
                {
                    mreDisposed.Set();
                }
            };

            while (dispatcher.GetQueueCount() != 2)
            {
            }

            dispatcher.Dispose();
            mre.Set();
            thread.Join();
            mreDisposed.Wait();

            Assert.IsFalse(invoked1);
            Assert.IsFalse(invoked2);
            Assert.AreEqual(invocationResult.Invocation.Status, InvocationStatus.Canceled);
            Assert.AreEqual(invocationResult1.Invocation.Status, InvocationStatus.Canceled);
        }
            public MarketDataObservable(CurrencyPair currencyPair, OcDispatcher backgroundOcDispatcher)
            {
                var spread  = currencyPair.DefaultSpread;
                var midRate = currencyPair.InitialPrice;
                var bid     = midRate - (spread * currencyPair.PipSize);
                var offer   = midRate + (spread * currencyPair.PipSize);
                var initial = new MarketData(currencyPair.Code, bid, offer);

                var currentPrice = initial;

                Value = currentPrice;

                var random = new Random();

                //for a given period, move prices by up to 5 pips
                _recurringAction = new RecurringAction(() =>
                {
                    int pips = random.Next(1, 5);
                    //move up or down between 1 and 5 pips
                    var adjustment        = Math.Round(pips * currencyPair.PipSize, currencyPair.DecimalPlaces);
                    MarketData marketData = random.NextDouble() > 0.5
                                                ? currentPrice + adjustment
                                                : currentPrice - adjustment;

                    backgroundOcDispatcher.Invoke(() =>
                                                  Value = marketData);
                }, () => TimeSpan.FromSeconds(1 / (double)currencyPair.TickFrequency));
            }
        public void TestFuncSyncState()
        {
            OcDispatcher dispatcher   = new OcDispatcher(2);
            object       returnObject = new object();

            Assert.AreEqual(dispatcher.Invoke(s => returnObject, new object()).Value, returnObject);
            dispatcher.Dispose();
        }
        public void TestInvocationBehaviourThrowException()
        {
            OcDispatcher dispatcher = new OcDispatcher();

            dispatcher.NewInvocationBehaviour = NewInvocationBehaviour.ThrowException;
            bool      called = false;
            Exception exception;

            void invoke(Action action)
            {
                exception = null;
                try
                {
                    action();
                }
                catch (Exception e)
                {
                    exception = e;
                }

                Assert.IsTrue(exception != null);
            }

            invoke(() => dispatcher.Invoke(() => { called = true; }));
            invoke(() => dispatcher.Invoke(s => { called = true; }, new object()));
            invoke(() => dispatcher.InvokeAsync(() => { called = true; }));
            invoke(() => dispatcher.InvokeAsync(s => { called = true; }, new object()));

            invoke(() => dispatcher.Invoke(() => { called = true; return(0); }));
            invoke(() => dispatcher.Invoke(s => { called = true; return(0); }, new object()));
            invoke(() => dispatcher.InvokeAsync(() => { called = true; return(0); }));
            invoke(() => dispatcher.InvokeAsync(s => { called = true; return(0); }, new object()));

            dispatcher.NewInvocationBehaviour = NewInvocationBehaviour.Accept;
            dispatcher.Pass();

            Assert.IsFalse(called);
            dispatcher.Dispose();
        }
        public TradeAgeUpdateJob(OcDispatcher backgroundOcDispatcher, ITradeService tradeService)
        {
            _recurringAction = new RecurringAction(() =>
            {
                Trade[] trades = null;

                backgroundOcDispatcher.Invoke(() =>
                                              trades = tradeService.All.ToArray());

                if (trades != null)
                {
                    foreach (IEnumerable <Trade> tradesSlice in trades.Split(300))
                    {
                        backgroundOcDispatcher.Invoke(() =>
                        {
                            foreach (Trade trade in tradesSlice)
                            {
                                TimeSpan diff = DateTime.Now.Subtract(trade.Timestamp);

                                TimePeriod age =
                                    diff.TotalSeconds <= 60 ? TimePeriod.LastMinute
                                                                        : diff.TotalMinutes <= 60 ? TimePeriod.LastHour
                                                                        : TimePeriod.Older;

                                trade.Age = age;

                                if (diff.TotalSeconds > 30)
                                {
                                    trade.Expired = true;
                                }
                            }
                        });
                    }
                }
            }, () => TimeSpan.FromSeconds(1));
        }
예제 #7
0
            public Item(int num, int num2, OcDispatcher mainOcDispatcher, OcDispatcher backgroundOcDispatcher)
            {
                _num  = num;
                _num2 = num2;
                _numBackgroundToMainDispatching        = new PropertyDispatching <Item, int>(this, nameof(Num), mainOcDispatcher, backgroundOcDispatcher).For(Consumer);
                _num2MainToBackgroundDispatching       = new PropertyDispatching <Item, int>(this, nameof(Num2), backgroundOcDispatcher, mainOcDispatcher).For(Consumer);
                _numBackgroundToMainScalarDispatching  = new Computing <int>(() => Num).ScalarDispatching(mainOcDispatcher, backgroundOcDispatcher).For(Consumer);
                _num2MainToBackgroundScalarDispatching = new Computing <int>(() => Num2).ScalarDispatching(backgroundOcDispatcher, mainOcDispatcher).For(Consumer);

                _numBackgroundToMainScalarDispatching.SetValueRequestHandler = i =>
                {
                    backgroundOcDispatcher.Invoke(() => Num = i);
                };

                _num2MainToBackgroundDispatching.PropertyChanged += (sender, args) =>
                {
                    if (Thread.CurrentThread != backgroundOcDispatcher._thread)
                    {
                        throw new Exception("Wrong thread");
                    }
                };

                _num2MainToBackgroundScalarDispatching.PropertyChanged += (sender, args) =>
                {
                    if (Thread.CurrentThread != backgroundOcDispatcher._thread)
                    {
                        throw new Exception("Wrong thread");
                    }
                };

                _numBackgroundToMainDispatching.PropertyChanged += (sender, args) =>
                {
                    if (Thread.CurrentThread != mainOcDispatcher._thread)
                    {
                        throw new Exception("Wrong thread");
                    }
                };

                _numBackgroundToMainScalarDispatching.PropertyChanged += (sender, args) =>
                {
                    if (Thread.CurrentThread != mainOcDispatcher._thread)
                    {
                        throw new Exception("Wrong thread");
                    }
                };
            }
        public void TestCallAwaitable()
        {
            TestSynchronizationConext testSynchronizationConext = new TestSynchronizationConext();

            SynchronizationContext.SetSynchronizationContext(testSynchronizationConext);

            OcDispatcher         dispatcher = new OcDispatcher(2);
            int                  count      = 1;
            ManualResetEventSlim mres       = new ManualResetEventSlim(false);
            object               context    = new object();
            Invocation           parent;


            dispatcher.InvokeAsync(() =>
            {
                parent = dispatcher.CurrentInvocation;

                dispatcher.Invoke(async() =>
                {
                    Assert.AreEqual(count, 1);
                    count++;
                    Assert.AreEqual(dispatcher.CurrentInvocation.Priority, 1);
                    Assert.AreEqual(dispatcher.CurrentInvocation.Context, context);
                    Assert.AreEqual(dispatcher.CurrentInvocation.Parent, parent);

                    OcDispatcherSynchronizationContext synchronizationContext = (OcDispatcherSynchronizationContext)SynchronizationContext.Current;
                    Assert.AreEqual(synchronizationContext.Priority, 1);
                    Assert.AreEqual(synchronizationContext.Context, context);
                    Assert.AreEqual(synchronizationContext.ParentInvocation, parent);

                    await Task.Run(() => count++);

                    Assert.AreEqual(dispatcher.CurrentInvocation.Priority, 1);
                    Assert.AreEqual(dispatcher.CurrentInvocation.Context, context);
                    Assert.AreEqual(dispatcher.CurrentInvocation.Parent, parent);
                    count++;
                    mres.Set();
                    return(1);
                }, 1, context, true);
            });

            mres.Wait();
            mres.Dispose();
            Assert.AreEqual(count, 4);
            dispatcher.Dispose();
        }
        public void TestInvokeAsyncAwaitableFuncStateDispatcherThread()
        {
            OcDispatcher         dispatcher = new OcDispatcher(2);
            int                  count      = 0;
            ManualResetEventSlim mres       = new ManualResetEventSlim(false);
            object               context    = new object();

            dispatcher.Invoke(() =>
            {
                Invocation invocation = dispatcher.CurrentInvocation;

                dispatcher.InvokeAsync(async() =>
                {
                    count++;
                    Assert.AreEqual(dispatcher.CurrentInvocation.Parent, invocation);
                    Assert.IsTrue(dispatcher.CurrentInvocation.SetSynchronizationContext);

                    int returnCount = await dispatcher.InvokeAsyncAwaitable(state =>
                    {
                        Assert.AreEqual(count, 1);
                        count++;
                        Assert.AreEqual(dispatcher.CurrentInvocation.Priority, 0);
                        Assert.AreEqual(dispatcher.CurrentInvocation.Context, null);
                        return(count);
                    }, new object());

                    Assert.AreEqual(dispatcher.CurrentInvocation.Parent, invocation);
                    Assert.AreEqual(returnCount, 2);
                    Assert.AreEqual(count, 2);
                    count++;
                    Assert.AreEqual(Thread.CurrentThread.ManagedThreadId, dispatcher.ManagedThreadId);
                    Assert.AreEqual(dispatcher.CurrentInvocation.Priority, 1);
                    Assert.AreEqual(dispatcher.CurrentInvocation.Context, context);
                    mres.Set();
                }, 1, context, true);
            });


            mres.Wait();
            mres.Dispose();
            Assert.AreEqual(count, 3);
            dispatcher.Dispose();
        }
예제 #10
0
        public TradeService(ILogger logger, TradeGenerator tradeGenerator, OcDispatcher backgroundOcDispatcher)
        {
            _logger                 = logger;
            _tradeGenerator         = tradeGenerator;
            _backgroundOcDispatcher = backgroundOcDispatcher;

            All  = new ObservableCollection <Trade>(_tradeGenerator.Generate(5_000, true));
            Live = All.Filtering(t => t.Status == TradeStatus.Live).For(_consumer);

            var random = new Random();

            TimeSpan RandomInterval() => TimeSpan.FromMilliseconds(random.Next(2500, 5000));

            // create a random number of trades at a random interval
            RecurringAction tradeEmitter = new RecurringAction(() =>
            {
                var number = random.Next(1, 5);
                var trades = _tradeGenerator.Generate(number);

                foreach (Trade trade in trades)
                {
                    _backgroundOcDispatcher.Invoke(() => All.Add(trade));
                }
            }, RandomInterval);

            List <Trade> closedTrades = new List <Trade>();
            //close a random number of trades at a random interval
            RecurringAction tradeCloser = new RecurringAction(() =>
            {
                var number = random.Next(1, 2);
                for (int i = 1; i <= number; i++)
                {
                    _backgroundOcDispatcher.Invoke(() =>
                    {
                        Trade trade          = All[random.Next(0, All.Count - 1)];
                        trade.Status         = TradeStatus.Closed;
                        trade.CloseTimestamp = DateTime.Now;
                        closedTrades.Add(trade);
                    });
                }
            }, RandomInterval);


            //expire closed items from the cache to avoid unbounded data
            RecurringAction tradeRemover = new RecurringAction(() =>
            {
                _backgroundOcDispatcher.Invoke(() =>
                {
                    for (var index = closedTrades.Count - 1; index >= 0; index--)
                    {
                        Trade closedTrade = closedTrades[index];
                        if ((DateTime.Now - closedTrade.CloseTimestamp).Minutes >= 1)
                        {
                            All.Remove(closedTrade);
                            closedTrades.RemoveAt(index);
                        }
                    }
                });
            }, () => TimeSpan.FromMinutes(1));



            //log changes
            OcDispatcher logPropertyChangedOcDispatcher = new OcDispatcher();

            LogChanges(logPropertyChangedOcDispatcher);

            _cleanup = new CompositeDisposable(
                _consumer, tradeEmitter, tradeCloser, logPropertyChangedOcDispatcher, tradeRemover);
        }
        public void TestDebugInfoState(
            [Values(true, false)] bool debug,
            [Values(true, false)] bool secondAsync)
        {
            OcConfiguration.SaveOcDispatcherInvocationInstantiationStackTrace = debug;

            object          context    = new object();
            object          state      = new object();
            OcDispatcher    dispatcher = new OcDispatcher(2);
            Action <object> action     = null;
            Invocation      parentInvocation;

            action = s =>
            {
                Assert.AreEqual(s, state);
                Assert.IsTrue(dispatcher.CheckAccess());

                Assert.AreEqual(OcDispatcher.Current, dispatcher);
                parentInvocation = dispatcher.CurrentInvocation;
                Assert.AreEqual(parentInvocation.Parent, null);
                Assert.AreEqual(parentInvocation.State, state);
                Assert.AreEqual(parentInvocation.Action, null);
                Assert.AreEqual(parentInvocation.ActionWithState, action);
                if (debug)
                {
                    Assert.IsTrue(parentInvocation.InstantiationStackTrace != null);
                }
                Assert.AreEqual(parentInvocation.Context, context);
                Assert.AreEqual(parentInvocation.OcDispatcher, dispatcher);
                Assert.AreEqual(parentInvocation.Priority, 1);

                object state1 = new object();

                Func <object, int> func1 = null;

                func1 = s1 =>
                {
                    Assert.IsTrue(dispatcher.CheckAccess());

                    Assert.AreEqual(OcDispatcher.Current, dispatcher);
                    Invocation invocation1 = dispatcher.CurrentInvocation;
                    Assert.AreEqual(invocation1.Parent, parentInvocation);
                    Assert.AreEqual(invocation1.State, state1);
                    Assert.AreEqual(invocation1.Action, null);
                    if (debug)
                    {
                        Assert.IsTrue(invocation1.InstantiationStackTrace != null);
                    }
                    Assert.AreEqual(invocation1.Context, null);
                    Assert.AreEqual(invocation1.OcDispatcher, dispatcher);
                    Assert.AreEqual(invocation1.Priority, 0);

                    return(3);
                };

                if (secondAsync)
                {
                    dispatcher.InvokeAsync(func1, state1).PropertyChanged += (sender, args) =>
                    {
                        if (args.PropertyName == "Value")
                        {
                            Assert.AreEqual(((InvocationResult <int>)sender).Value, 3);
                        }
                    };
                }
                else
                {
                    Assert.AreEqual(dispatcher.Invoke(func1, state1).Value, 3);
                }
            };

            Assert.IsFalse(dispatcher.CheckAccess());
            dispatcher.Invoke(action, state, 1, context);

            dispatcher.Pass();
            dispatcher.Pass();
            Assert.AreEqual(dispatcher, StaticInfo.OcDispatchers[dispatcher.ManagedThreadId]);
            Assert.IsTrue(dispatcher.CurrentInvocation == null);
            Assert.IsTrue(OcDispatcher.Current == null);
            dispatcher.Dispose();
        }
        public void TestSetThreadProperites()
        {
            OcConfiguration.SaveInstantiationStackTrace = true;
            OcDispatcher dispatcher = new OcDispatcher(2);

            Assert.AreEqual(dispatcher.GetQueueCount(0), 0);
            Assert.AreEqual(dispatcher.GetQueueCount(), 0);
            Assert.IsTrue(dispatcher.InstantiationStackTrace != null);
            ApartmentState apartmentState = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ?  ApartmentState.Unknown : ApartmentState.MTA;

            Assert.AreEqual(dispatcher.NewInvocationBehaviour, NewInvocationBehaviour.Accept);
            Assert.AreEqual(dispatcher.Status, OcDispatcherStatus.ExecutingOrWait);
            Assert.AreEqual(dispatcher.GetThreadApartmentState(), apartmentState);
            Assert.AreEqual(dispatcher.PrioritiesNumber, 2);
            CultureInfo culture = CultureInfo.GetCultureInfo("ru-RU");

            dispatcher.ThreadIsBackground = true;
            dispatcher.ThreadName         = "ThreadName";
            Assert.AreEqual(dispatcher.ToString(), "(ObservableComputations.OcDispatcher (Thread.Name = 'ThreadName'))");
            dispatcher.ThreadPriority = ThreadPriority.Highest;
            int managedThreadId = dispatcher.ManagedThreadId;

            Assert.IsTrue(dispatcher.ThreadState == (ThreadState.WaitSleepJoin | ThreadState.Background) || dispatcher.ThreadState == (ThreadState.Running | ThreadState.Background));

            Assert.AreEqual(dispatcher.ThreadIsBackground, true);
            Assert.AreEqual(dispatcher.ThreadName, "ThreadName");
            Assert.AreEqual(dispatcher.ThreadPriority, ThreadPriority.Highest);
            Assert.AreEqual(dispatcher.ThreadIsAlive, true);
            Assert.AreEqual(dispatcher.ManagedThreadId, managedThreadId);
            Assert.AreEqual(dispatcher.GetThreadApartmentState(), apartmentState);


            dispatcher.Invoke(() =>
            {
                dispatcher.ThreadCurrentCulture   = culture;
                dispatcher.ThreadCurrentUICulture = culture;
                Assert.AreEqual(Thread.CurrentThread.CurrentCulture, culture);
                Assert.AreEqual(Thread.CurrentThread.CurrentUICulture, culture);
                Assert.AreEqual(dispatcher.ThreadCurrentCulture, culture);
                Assert.AreEqual(dispatcher.ThreadCurrentUICulture, culture);
                Assert.AreEqual(Thread.CurrentThread.IsBackground, true);
                Assert.AreEqual(Thread.CurrentThread.Name, "ThreadName");
                Assert.AreEqual(Thread.CurrentThread.Priority, ThreadPriority.Highest);
                Assert.AreEqual(Thread.CurrentThread.IsAlive, true);
                Assert.AreEqual(dispatcher.ThreadExecutionContext, Thread.CurrentThread.ExecutionContext);
                Assert.AreEqual(Thread.CurrentThread.ManagedThreadId, managedThreadId);
                Assert.AreEqual(Thread.CurrentThread.GetApartmentState(), apartmentState);
            });

            ManualResetEventSlim mreDisposed = new ManualResetEventSlim(false);

            dispatcher.PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == nameof(OcDispatcher.Status) &&
                    dispatcher.Status == OcDispatcherStatus.Disposed)
                {
                    mreDisposed.Set();
                }
            };

            dispatcher.Dispose();
            Assert.AreEqual(dispatcher.NewInvocationBehaviour, NewInvocationBehaviour.Cancel);

            Exception exception = null;

            try
            {
                dispatcher.NewInvocationBehaviour = NewInvocationBehaviour.Accept;
            }
            catch (Exception e)
            {
                exception = e;
            }

            Assert.IsNotNull(exception);

            mreDisposed.Wait();
            Assert.AreEqual(dispatcher.Status, OcDispatcherStatus.Disposed);
        }