/// <summary> /// Observers (subscribers) will receive notifications on the specified /// SynchronizationContext. For subscribers which need to manipulate GUI /// make sure this is the GUI SynchronizationContext. /// </summary> public Behaviour <A> ObserveOn(SynchronizationContext context) { var r = new Behaviour <A>(Value); Subject.ObserveOn(context).Subscribe(r.Subject); return(r); }
public AppUserModelService(IUserApiService userApiService, ILogger logger, IAppSettings appSettings) { _favouriteCakes = new SourceCache <CakeDto, int>(c => c.Id); _appSettings = appSettings; _userIdSubject = new BehaviorSubject <string>(String.Empty); _userSubject = new BehaviorSubject <UserDto>(null); _cd = new CompositeDisposable(); _favouriteCakes .Connect() .CacheChangeSet(CacheKey, logger) .Subscribe(); _userIdSubject .ObserveOn(RxApp.TaskpoolScheduler) .Where(u => u != null) .SelectMany(async uId => await userApiService.GetFavourites(uId)) .RetryWithBackoff(3) .LogException(logger) .Subscribe(cakes => { _favouriteCakes.Edit(l => l.AddOrUpdate(cakes)); }) .DisposeWith(_cd); Observable.FromAsync(async() => await _favouriteCakes.FromCache(CacheKey, EqualityComparer <CakeDto> .Default)).Subscribe().DisposeWith(_cd); }
public EditableTableViewModel(IAlertController alerts, INavigationService navigationService, ISchedulerService schedulerService) : base(navigationService, schedulerService) { Intent = TableIntent.Form; // More common? _alerts = alerts; _toggleEditModeCommand = new Command((obj) => ToggleEditMode()); _editBarItem = new TextToolbarItemViewModel("Edit", _toggleEditModeCommand); _editMode.ObserveOn(schedulerService.UiScheduler).Subscribe((em) => { _editBarItem.Text = em ? DoneButtonCaption : EditButtonCaption; Sections.ForEach(s => s.EditMode = em); }); Toolbar.Add(_editBarItem); }
public void ReadonlyCollectionDynamicData() { var scheduler = new TestScheduler(); var list = new SourceList <int>(); var filterFunc = new BehaviorSubject <Func <int, bool> >(x => true); list.Connect() //if you comment out the filter or the observeon then this passes .Filter(filterFunc.ObserveOn(scheduler)) .ObserveOn(scheduler) .Bind(out var oc) .Subscribe(); list.Edit(updateAction => { updateAction.Add(1); updateAction.Add(2); updateAction.Add(3); }); scheduler.Start(); oc.Count.Should().Be(3); list.Edit(updateAction => { updateAction.Remove(1); updateAction.Remove(2); updateAction.Remove(3); updateAction.Count.Should().Be(0); updateAction.Add(4); updateAction.Add(5); updateAction.Add(6); }); scheduler.Start(); //This fails and those other update actions aren't removed oc.Count.Should().Be(3); }
public IObservable <string> ExecutablesChanged() { _watcher = new FileSystemWatcher { Path = _configuration.ServiceBinPath, NotifyFilter = NotifyFilters.LastWrite, EnableRaisingEvents = true }; _watcher.Changed += (_, fileInfo) => { if (!(fileInfo.FullPath.EndsWith(".exe") || fileInfo.FullPath.EndsWith(".dll") || fileInfo.FullPath.EndsWith(".config"))) { return; } _observable.OnNext(_configuration.StartupFile); }; return(_observable .ObserveOn(Scheduler.Default) .Throttle(TimeSpan.FromSeconds(20))); }
public AppConnectionsSet(UniqueId appInstanceId) { _appInstanceId = appInstanceId; UpdatedEventStream = _updatedSubject.ObserveOn(TaskPoolScheduler.Default); }
public void ThreadSwitching() { Console.WriteLine("Starting Thread " + Thread.CurrentThread.ManagedThreadId); BehaviorSubject<int> s1 = new BehaviorSubject<int>(2); BehaviorSubject<int> s2 = new BehaviorSubject<int>(3); BehaviorSubject<int> sum = new BehaviorSubject<int>(5); List<int> computeThreads = new List<int>(); List<int> receiveThreads = new List<int>(); IScheduler switchScheduler = new EventLoopScheduler(); IScheduler computeScheduler = new EventLoopScheduler(); IObservable<int> sumObservable = s1.Select(v => new Tuple<int, int>(v, s2.Value)).Merge(s2.Select(v => new Tuple<int, int>(s1.Value, v))).Throttle(TimeSpan.FromMilliseconds(100), switchScheduler).Select(v => { Console.WriteLine("Not yet switching computing value " + v.Item1 + " + " + v.Item2 + " = " + (v.Item1 + v.Item2) + " from Thread " + Thread.CurrentThread.ManagedThreadId + "."); return v; }).Select(v => { Console.WriteLine("Switching computing value " + v.Item1 + " + " + v.Item2 + " = " + (v.Item1 + v.Item2) + " from Thread " + Thread.CurrentThread.ManagedThreadId + "."); return v; }).ObserveOn(computeScheduler).Select(v => { Console.WriteLine("Already switched computing value " + v.Item1 + " + " + v.Item2 + " = " + (v.Item1 + v.Item2) + " to Thread " + Thread.CurrentThread.ManagedThreadId + "."); return v; }).Select(v => { Console.WriteLine("Computing value " + v.Item1 + " + " + v.Item2 + " = " + (v.Item1 + v.Item2) + " on Thread " + Thread.CurrentThread.ManagedThreadId + "."); computeThreads.Add(Thread.CurrentThread.ManagedThreadId); return v.Item1 + v.Item2; }); sumObservable.Subscribe(sum.OnNext); sum.ObserveOn(new EventLoopScheduler()).Subscribe(v => { Console.WriteLine("Received value " + v + " on Thread " + Thread.CurrentThread.ManagedThreadId + "."); receiveThreads.Add(Thread.CurrentThread.ManagedThreadId); }); Thread.Sleep(150); s2.OnNext(1); Thread.Sleep(50); s1.OnNext(4); Thread.Sleep(150); s2.OnNext(4); Thread.Sleep(250); s1.OnNext(1); Thread.Sleep(150); foreach (KeyValuePair<int, int> p in computeThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count()))) { Console.WriteLine(p.Value + " computes on Thread " + p.Key); } foreach (KeyValuePair<int, int> p in receiveThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count()))) { Console.WriteLine(p.Value + " receives on Thread " + p.Key); } }
public void RxOnlyAsyncObservableThreadsWithBetterThrottleOnComputeAndIsCalculating() { Console.WriteLine("Starting Thread " + Thread.CurrentThread.ManagedThreadId); BehaviorSubject<int> s1 = new BehaviorSubject<int>(2); BehaviorSubject<int> s2 = new BehaviorSubject<int>(3); List<int> computeThreads = new List<int>(); List<int> receiveThreads = new List<int>(); IScheduler throttleScheduler = new EventLoopScheduler(); IScheduler computeScheduler = NewThreadScheduler.Default; IScheduler receiveScheduler = new EventLoopScheduler(); IObservable<Tuple<int, int>> sumObservable = s1.CombineLatest(s2, Tuple.Create).Throttle(TimeSpan.FromMilliseconds(100), throttleScheduler); Func<CalculatedPropertyHelper, int, int, Task<int>> calculate = async (helper, v1, v2) => { Thread.Sleep(200); helper.CheckCancellationToken(); Console.WriteLine("Computing value " + v1 + " + " + v2 + " = " + (v1 + v2) + " on Thread " + Thread.CurrentThread.ManagedThreadId + "."); computeThreads.Add(Thread.CurrentThread.ManagedThreadId); return await Task.FromResult(v1 + v2); }; BehaviorSubject<int> sum = new BehaviorSubject<int>(0); IDisposable scheduledTask = computeScheduler.ScheduleAsync(async (scheduler, token) => { await scheduler.Yield(); sum.OnNext(await calculate(new CalculatedPropertyHelper(scheduler, token), s1.Value, s2.Value)); }); using (sumObservable.Subscribe(v => { if (scheduledTask != null) { Console.WriteLine("Canceling previous."); scheduledTask.Dispose(); } scheduledTask = computeScheduler.ScheduleAsync(async (scheduler, token) => { await scheduler.Yield(); sum.OnNext(await calculate(new CalculatedPropertyHelper(scheduler, token), v.Item1, v.Item2)); }); })) { using (sum.ObserveOn(receiveScheduler).Subscribe(v2 => { Console.WriteLine("Received value " + v2 + " on Thread " + Thread.CurrentThread.ManagedThreadId + "."); receiveThreads.Add(Thread.CurrentThread.ManagedThreadId); })) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Thread.Sleep(150); s2.OnNext(1); Thread.Sleep(50); s1.OnNext(4); Thread.Sleep(250); s2.OnNext(4); Thread.Sleep(150); s1.OnNext(1); Thread.Sleep(350); stopwatch.Stop(); Console.WriteLine("Total Time: " + stopwatch.ElapsedMilliseconds + " ms"); foreach (KeyValuePair<int, int> p in computeThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count()))) { Console.WriteLine(p.Value + " computes on Thread " + p.Key); } foreach (KeyValuePair<int, int> p in receiveThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count()))) { Console.WriteLine(p.Value + " receives on Thread " + p.Key); } } } }
public void ObservableThreadsWithThrottleOnCompute() { Console.WriteLine("Starting Thread " + Thread.CurrentThread.ManagedThreadId); BehaviorSubject<int> s1 = new BehaviorSubject<int>(2); BehaviorSubject<int> s2 = new BehaviorSubject<int>(3); BehaviorSubject<int> sum = new BehaviorSubject<int>(5); List<int> computeThreads = new List<int>(); List<int> receiveThreads = new List<int>(); IScheduler computeScheduler = new EventLoopScheduler(); IObservable<int> sumObservable = s1.Throttle(TimeSpan.FromMilliseconds(100), computeScheduler).ObserveOn(computeScheduler).CombineLatest(s2.Throttle(TimeSpan.FromMilliseconds(100), computeScheduler).ObserveOn(computeScheduler), (first, second) => { Console.WriteLine("Computing value " + first + " + " + second + " = " + (first + second) + " on Thread " + Thread.CurrentThread.ManagedThreadId + "."); computeThreads.Add(Thread.CurrentThread.ManagedThreadId); return first + second; }); sumObservable.Subscribe(sum.OnNext); sum.ObserveOn(new EventLoopScheduler()).Subscribe(v => { Console.WriteLine("Received value " + v + " on Thread " + Thread.CurrentThread.ManagedThreadId + "."); receiveThreads.Add(Thread.CurrentThread.ManagedThreadId); }); Thread.Sleep(150); s2.OnNext(1); Thread.Sleep(50); s1.OnNext(4); Thread.Sleep(150); s2.OnNext(4); Thread.Sleep(250); s1.OnNext(1); Thread.Sleep(150); foreach (KeyValuePair<int, int> p in computeThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count()))) { Console.WriteLine(p.Value + " computes on Thread " + p.Key); } foreach (KeyValuePair<int, int> p in receiveThreads.GroupBy(v => v).Select(g => new KeyValuePair<int, int>(g.Key, g.Count()))) { Console.WriteLine(p.Value + " receives on Thread " + p.Key); } }