This class supports throttling of multiple method calls to improve the responsiveness of an application. It delays a method call and skips all additional calls of this method during the delay. The call of the action is synchronized. It uses the current synchronization context that was active during creating this class.
This class is thread-safe.
예제 #1
0
        public void InvokeOnlyIfIdleForDelayTimeWithoutSynchronizationContext()
        {
            Assert.IsNull(SynchronizationContext.Current);

            int actionCallCount = 0;
            var throttledAction = new ThrottledAction(() => Interlocked.Add(ref actionCallCount, 1), ThrottledActionMode.InvokeOnlyIfIdleForDelayTime, TimeSpan.FromMilliseconds(100));
            Assert.IsFalse(throttledAction.IsRunning);

            throttledAction.InvokeAccumulated();
            Assert.IsTrue(throttledAction.IsRunning);
            throttledAction.InvokeAccumulated();
            throttledAction.InvokeAccumulated();

            // Multiple calls of InvokeAccumulated within the delayTime should call the action just once.
            Task.Delay(200).Wait();
            Assert.AreEqual(1, actionCallCount);
            Assert.IsFalse(throttledAction.IsRunning);

            actionCallCount = 0;
            throttledAction.InvokeAccumulated();
            Task.Delay(60).Wait();
            throttledAction.InvokeAccumulated();
            Task.Delay(60).Wait();
            throttledAction.InvokeAccumulated();
            Task.Delay(60).Wait();
            throttledAction.InvokeAccumulated();

            // Calls just once: The waits between InvokeAccumulated are less than the idle (delay) time.
            Task.Delay(200).Wait();
            Assert.AreEqual(1, actionCallCount);
            Assert.IsFalse(throttledAction.IsRunning);
        }
예제 #2
0
 public WorkspaceController(IDocumentService documentService, Lazy<ShellViewModel> shellViewModel, Lazy<ErrorListViewModel> errorListViewModel, 
     Lazy<OutputViewModel> outputViewModel, ScriptHost host)
 {
     taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
     this.documentService = documentService;
     this.shellViewModel = shellViewModel;
     this.errorListViewModel = errorListViewModel;
     this.outputViewModel = outputViewModel;
     this.host = host;
     this.updateDiagnosticsAction = new ThrottledAction(UpdateDiagnostics, ThrottledActionMode.InvokeOnlyIfIdleForDelayTime, TimeSpan.FromSeconds(2));
     this.outputTextWriter = new DelegateTextWriter(AppendOutputText);
     this.errorTextWriter = new DelegateTextWriter(AppendErrorText);
     this.startCommand = new DelegateCommand(StartScript, CanStartScript);
     this.stopCommand = new DelegateCommand(StopScript, CanStopScript);
     this.documentIds = new Dictionary<DocumentFile, DocumentId>();
 }
예제 #3
0
        public void InvokeMaxEveryDelayTimeTestWithoutSynchronizationContext()
        {
            Assert.IsNull(SynchronizationContext.Current);
            
            int actionCallCount = 0;
            var throttledAction = new ThrottledAction(() => Interlocked.Add(ref actionCallCount, 1), ThrottledActionMode.InvokeMaxEveryDelayTime, TimeSpan.FromMilliseconds(100));
            Assert.IsFalse(throttledAction.IsRunning);
            
            throttledAction.InvokeAccumulated();
            Assert.IsTrue(throttledAction.IsRunning);
            throttledAction.InvokeAccumulated();
            throttledAction.InvokeAccumulated();

            // Multiple calls of InvokeAccumulated within the delayTime should call the action just once.
            Task.Delay(200).Wait();
            Assert.AreEqual(1, actionCallCount);
            Assert.IsFalse(throttledAction.IsRunning);


            actionCallCount = 0;
            throttledAction.InvokeAccumulated();
            Task.Delay(10).Wait();
            throttledAction.InvokeAccumulated();
            Task.Delay(150).Wait();
            throttledAction.InvokeAccumulated();

            // Calls the action twice: First 2 InvokeAccumulated are within delayTime; Last is after delayTime.
            Task.Delay(200).Wait();
            Assert.AreEqual(2, actionCallCount);
            Assert.IsFalse(throttledAction.IsRunning);


            actionCallCount = 0;
            throttledAction.InvokeAccumulated();
            Task.Delay(10).Wait();
            throttledAction.Cancel();

            // Do not call the action because it is cancelled. 
            Task.Delay(200).Wait();
            Assert.AreEqual(0, actionCallCount);
            Assert.IsFalse(throttledAction.IsRunning);
        }
예제 #4
0
        public PlayerView(PlayerService playerService)
        {
            this.InitializeComponent();
            this.viewModel = new Lazy<PlayerViewModel>(() => ViewHelper.GetViewModel<PlayerViewModel>(this));
            this.playerService = playerService;
            this.mediaPlayer = new MediaPlayer();
            this.duratonConverter = new Converters.DurationConverter();

            updateTimer = new DispatcherTimer();
            updateTimer.Interval = TimeSpan.FromMilliseconds(100);
            updateTimer.Tick += UpdateTimerTick;

            throttledSliderValueChangedAction = new ThrottledAction(ThrottledSliderValueChanged, ThrottledActionMode.InvokeMaxEveryDelayTime, TimeSpan.FromMilliseconds(100));

            previousCommand = new DelegateCommand(Previous, CanPrevious);
            playPauseCommand = new DelegateCommand(PlayPause, CanPlayPause);
            nextCommand = new DelegateCommand(Next, CanNext);
            playerService.PreviousCommand = previousCommand;
            playerService.PlayPauseCommand = playPauseCommand;
            playerService.NextCommand = nextCommand;
            playerService.IsPlayCommand = true;
            
            Loaded += FirstTimeLoadedHandler;
        }
예제 #5
0
        public void InvokeMaxEveryDelayTimeTestWithSynchronizationContext()
        {
            using (var context = UnitTestSynchronizationContext.Create())
            {
                int actionCallCount = 0;
                var throttledAction = new ThrottledAction(() => Interlocked.Add(ref actionCallCount, 1), ThrottledActionMode.InvokeMaxEveryDelayTime, TimeSpan.FromMilliseconds(100));
                Assert.IsFalse(throttledAction.IsRunning);

                throttledAction.InvokeAccumulated();
                Assert.IsTrue(throttledAction.IsRunning);
                throttledAction.InvokeAccumulated();
                throttledAction.InvokeAccumulated();

                // As long the unit test synchronization context is not executed the actionCallCount must not be increased.
                Task.Delay(200).Wait();
                Assert.AreEqual(0, actionCallCount);

                // Execute the unit test synchronization context.
                context.WaitFor(() => actionCallCount > 0, TimeSpan.FromMilliseconds(200));
                Assert.AreEqual(1, actionCallCount);
                Assert.IsFalse(throttledAction.IsRunning);
            }
        }
예제 #6
0
 public void ConstructorTest()
 {
     AssertHelper.ExpectedException<ArgumentNullException>(() => new ThrottledAction(null));
     var throttledAction = new ThrottledAction(() => { });
     Assert.IsFalse(throttledAction.IsRunning);
 }