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)); }
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(); }
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); }