public void Wait_QueuesWork() { var l = new AsyncLock(); var l1 = false; var l2 = false; l.Wait(() => { l.Wait(() => { Assert.IsTrue(l1); l2 = true; }); l1 = true; }); Assert.IsTrue(l2); }
private void Tick(object state) { _gate.Wait(() => { _state = _action(_state); }); }
/// <summary> /// Schedules a periodic piece of work, using a System.Threading.Timer object. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">Initial state passed to the action upon the first iteration.</param> /// <param name="period">Period for running the work periodically.</param> /// <param name="action">Action to be executed, potentially updating the state.</param> /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than TimeSpan.Zero.</exception> /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception> public IDisposable SchedulePeriodic <TState>(TState state, TimeSpan period, Func <TState, TState> action) { if (period < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(period)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } var state1 = state; var gate = new AsyncLock(); var cancel = s_cal.StartPeriodicTimer(() => { gate.Wait(() => { state1 = action(state1); }); }, period); return(Disposable.Create(() => { cancel.Dispose(); gate.Dispose(); action = Stubs <TState> .I; })); }
/// <summary> /// Schedules a periodic piece of work by running a platform-specific timer to create tasks periodically. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">Initial state passed to the action upon the first iteration.</param> /// <param name="period">Period for running the work periodically.</param> /// <param name="action">Action to be executed, potentially updating the state.</param> /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than TimeSpan.Zero.</exception> public IDisposable SchedulePeriodic <TState>(TState state, TimeSpan period, Func <TState, TState> action) { if (period < TimeSpan.Zero) { throw new ArgumentOutOfRangeException("period"); } if (action == null) { throw new ArgumentNullException("action"); } #if !NO_TASK_DELAY var cancel = new CancellationDisposable(); var state1 = state; var gate = new AsyncLock(); var moveNext = default(Action); moveNext = () => { #if USE_TASKEX TaskEx.Delay(period, cancel.Token).ContinueWith( #else Task.Delay(period, cancel.Token).ContinueWith( #endif _ => { moveNext(); gate.Wait(() => { state1 = action(state1); }); }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, taskFactory.Scheduler ); }; moveNext(); return(new CompositeDisposable(cancel, gate)); #else var state1 = state; var gate = new AsyncLock(); var timer = ConcurrencyAbstractionLayer.Current.StartPeriodicTimer(() => { taskFactory.StartNew(() => { gate.Wait(() => { state1 = action(state1); }); }); }, period); return(new CompositeDisposable(timer, gate)); #endif }
public void Wait_Fail() { var l = new AsyncLock(); var ex = new Exception(); try { l.Wait(() => { throw ex; }); Assert.Fail(); } catch (Exception e) { Assert.AreSame(ex, e); } // has faulted; should not run l.Wait(() => { Assert.Fail(); }); }
private void Tick() { _gate.Wait( this, @this => { @this._state = @this._action(@this._state); }); }
/// <summary> /// Schedules a periodic piece of work by running a platform-specific timer to create tasks periodically. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">Initial state passed to the action upon the first iteration.</param> /// <param name="period">Period for running the work periodically.</param> /// <param name="action">Action to be executed, potentially updating the state.</param> /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than <see cref="TimeSpan.Zero"/>.</exception> public IDisposable SchedulePeriodic <TState>(TState state, TimeSpan period, Func <TState, TState> action) { if (period < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(period)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } var cancel = new CancellationDisposable(); var state1 = state; var gate = new AsyncLock(); var moveNext = default(Action); moveNext = () => { //TaskHelpers.Delay(period, cancel.Token).ContinueWith( // _ => // { // moveNext(); // gate.Wait(() => // { // state1 = action(state1); // }); // }, //CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, taskFactory.Scheduler TaskHelpers.Delay(period, cancel.Token).ContinueWith( t => { if (!t.IsCompletedSuccessfully) { return; } moveNext(); gate.Wait(() => { state1 = action(state1); }); }, CancellationToken.None ); }; moveNext(); return(StableCompositeDisposable.Create(cancel, gate)); }
private IDisposable Tick(IScheduler self) { _next += _period; Disposable.TrySetMultiple(ref _task, self.Schedule(this, _next - _scheduler._stopwatch.Elapsed, (_, s) => s.Tick(_))); _gate.Wait( this, closureWorkItem => closureWorkItem._state = closureWorkItem._action(closureWorkItem._state)); return(Disposable.Empty); }
public void Dispose() { var l = new AsyncLock(); var l1 = false; var l2 = false; var l3 = false; var l4 = false; l.Wait(() => { l.Wait(() => { l.Wait(() => { l3 = true; }); l2 = true; l.Dispose(); l.Wait(() => { l4 = true; }); }); l1 = true; }); Assert.IsTrue(l1); Assert.IsTrue(l2); Assert.IsFalse(l3); Assert.IsFalse(l4); }
public override IDisposable Schedule <TState>(TState state, Func <IScheduler, TState, IDisposable> action) { if (action == null) { throw new ArgumentNullException("action"); } var m = new SingleAssignmentDisposable(); if (asyncLock == null) { asyncLock = new AsyncLock(); } asyncLock.Wait(() => { if (!m.IsDisposed) { m.Disposable = action(this, state); } }); return(m); }
/// <summary> /// Schedules a periodic piece of work, using a Windows.System.Threading.ThreadPoolTimer object. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">Initial state passed to the action upon the first iteration.</param> /// <param name="period">Period for running the work periodically.</param> /// <param name="action">Action to be executed, potentially updating the state.</param> /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than one millisecond.</exception> public IDisposable SchedulePeriodic <TState>(TState state, TimeSpan period, Func <TState, TState> action) { // The WinRT thread pool is based on the Win32 thread pool and cannot handle // sub-1ms resolution. When passing a lower period, we get single-shot // timer behavior instead. See MSDN documentation for CreatePeriodicTimer // for more information. if (period < TimeSpan.FromMilliseconds(1)) { throw new ArgumentOutOfRangeException(nameof(period), "The WinRT thread pool doesn't support creating periodic timers with a period below 1 millisecond."); } if (action == null) { throw new ArgumentNullException(nameof(action)); } var state1 = state; var gate = new AsyncLock(); WasmRuntime.ScheduleTimeout( (int)period.TotalMilliseconds, () => { Action run = null; run = () => { gate.Wait(() => { state1 = action(state1); WasmRuntime.ScheduleTimeout( (int)period.TotalMilliseconds, run); }); }; }); return(Disposable.Create(() => { gate.Dispose(); action = Stubs <TState> .I; })); }
/// <summary> /// Schedules a periodic piece of work on the designated thread. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">Initial state passed to the action upon the first iteration.</param> /// <param name="period">Period for running the work periodically.</param> /// <param name="action">Action to be executed, potentially updating the state.</param> /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than <see cref="TimeSpan.Zero"/>.</exception> /// <exception cref="ObjectDisposedException">The scheduler has been disposed and doesn't accept new work.</exception> public IDisposable SchedulePeriodic <TState>(TState state, TimeSpan period, Func <TState, TState> action) { if (period < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(period)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } var start = _stopwatch.Elapsed; var next = start + period; var state1 = state; var td = new TernaryDisposable(); var gate = new AsyncLock(); td.Extra = gate; var tick = default(Func <IScheduler, object, IDisposable>); tick = (self_, _) => { next += period; td.Next = self_.Schedule(null, next - _stopwatch.Elapsed, tick); gate.Wait(() => { state1 = action(state1); }); return(Disposable.Empty); }; td.First = Schedule(null, next - _stopwatch.Elapsed, tick); return(td); }
/// <summary> /// Schedules a periodic piece of work on the designated thread. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">Initial state passed to the action upon the first iteration.</param> /// <param name="period">Period for running the work periodically.</param> /// <param name="action">Action to be executed, potentially updating the state.</param> /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than <see cref="TimeSpan.Zero"/>.</exception> /// <exception cref="ObjectDisposedException">The scheduler has been disposed and doesn't accept new work.</exception> public IDisposable SchedulePeriodic <TState>(TState state, TimeSpan period, Func <TState, TState> action) { if (period < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(period)); } if (action == null) { throw new ArgumentNullException(nameof(action)); } var start = _stopwatch.Elapsed; var next = start + period; var state1 = state; var d = new MultipleAssignmentDisposable(); var gate = new AsyncLock(); var tick = default(Func <IScheduler, object, IDisposable>); tick = (self_, _) => { next += period; d.Disposable = self_.Schedule(null, next - _stopwatch.Elapsed, tick); gate.Wait(() => { state1 = action(state1); }); return(Disposable.Empty); }; d.Disposable = Schedule(null, next - _stopwatch.Elapsed, tick); return(StableCompositeDisposable.Create(d, gate)); }
/// <summary> /// Schedules a periodic piece of work, using a Windows.System.Threading.ThreadPoolTimer object. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">Initial state passed to the action upon the first iteration.</param> /// <param name="period">Period for running the work periodically.</param> /// <param name="action">Action to be executed, potentially updating the state.</param> /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than one millisecond.</exception> public IDisposable SchedulePeriodic <TState>(TState state, TimeSpan period, Func <TState, TState> action) { // // The WinRT thread pool is based on the Win32 thread pool and cannot handle // sub-1ms resolution. When passing a lower period, we get single-shot // timer behavior instead. See MSDN documentation for CreatePeriodicTimer // for more information. // if (period < TimeSpan.FromMilliseconds(1)) { throw new ArgumentOutOfRangeException(nameof(period), Strings_PlatformServices.WINRT_NO_SUB1MS_TIMERS); } if (action == null) { throw new ArgumentNullException(nameof(action)); } var state1 = state; var gate = new AsyncLock(); var res = global::Windows.System.Threading.ThreadPoolTimer.CreatePeriodicTimer( tpt => { gate.Wait(() => { state1 = action(state1); }); }, period ); return(Disposable.Create(() => { res.Cancel(); gate.Dispose(); action = Stubs <TState> .I; })); }
private void Tick(ThreadPoolTimer timer) { _gate.Wait( this, @this => @this._state = @this._action(@this._state)); }
private void Tick() { _gate.Wait( this, closureWorkItem => closureWorkItem._state = closureWorkItem._action(closureWorkItem._state)); }
public void Wait_ArgumentChecking() { var asyncLock = new AsyncLock(); asyncLock.Wait(null); }
public void Wait_ArgumentChecking() { var asyncLock = new AsyncLock(); Assert.Throws<ArgumentNullException>(() => asyncLock.Wait(null)); }