public async void Start(TimeSpan interval) { if (interval < TimeSpan.Zero) throw new ArgumentOutOfRangeException("interval"); lock (_stateLock) { if (_state == PortableTimerState.Disposed) throw new ObjectDisposedException("PortableTimer"); if (_state == PortableTimerState.Waiting) throw new InvalidOperationException("The timer already set"); if (_cancel.IsCancellationRequested) return; _state = PortableTimerState.Waiting; } try { await Task.Delay(interval, _cancel.Token); } finally { lock (_stateLock) _state = PortableTimerState.NotWaiting; } if (!_cancel.Token.IsCancellationRequested) { await Task.Run(() => _onTick(_cancel.Token)); } }
public async void Start(TimeSpan interval) { if (interval < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(interval)); } lock (_stateLock) { if (_state == PortableTimerState.Disposed) { throw new ObjectDisposedException("PortableTimer"); } // There's a little bit of raciness here, but it's needed to support the // current API, which allows the tick handler to reenter and set the next interval. if (_state == PortableTimerState.Waiting) { throw new InvalidOperationException("The timer is already set."); } if (_cancel.IsCancellationRequested) { return; } _state = PortableTimerState.Waiting; } try { if (interval > TimeSpan.Zero) { await Task.Delay(interval, _cancel.Token).ConfigureAwait(false); } _state = PortableTimerState.Active; if (!_cancel.Token.IsCancellationRequested) { _onTick(_cancel.Token); } } catch (TaskCanceledException tcx) { SelfLog.WriteLine("The timer was canceled during invocation: {0}", tcx); } finally { lock (_stateLock) _state = PortableTimerState.NotWaiting; } }
public async void Start(TimeSpan interval) { if (interval < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(interval)); } lock (_stateLock) { if (_state == PortableTimerState.Disposed) { throw new ObjectDisposedException("PortableTimer"); } if (_state == PortableTimerState.Waiting) { throw new InvalidOperationException("The timer already set"); } if (_cancel.IsCancellationRequested) { return; } _state = PortableTimerState.Waiting; } try { if (!_cancel.Token.IsCancellationRequested) { await Task.Delay(interval, _cancel.Token); } } catch (TaskCanceledException) when(_cancel.IsCancellationRequested) { // currently disposing } finally { lock (_stateLock) _state = PortableTimerState.NotWaiting; } if (!_cancel.Token.IsCancellationRequested) { await Task.Run(() => _onTick(_cancel.Token)); } }
public void Dispose() { _cancel.Cancel(); while (true) { // Thread.Sleep() would be handy here... lock (_stateLock) { if (_state == PortableTimerState.Disposed || _state == PortableTimerState.NotWaiting) { _state = PortableTimerState.Disposed; return; } } } }
public void Dispose() { _cancel.Cancel(); while (true) { lock (_stateLock) { if (_state == PortableTimerState.Disposed || _state == PortableTimerState.NotWaiting) { _state = PortableTimerState.Disposed; return; } } Thread.Sleep(10); } }
public async void Start(TimeSpan interval) { if (interval < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(interval)); lock (_stateLock) { if (_state == PortableTimerState.Disposed) throw new ObjectDisposedException("PortableTimer"); // There's a little bit of raciness here, but it's needed to support the // current API, which allows the tick handler to reenter and set the next interval. if (_state == PortableTimerState.Waiting) throw new InvalidOperationException("The timer is already set."); if (_cancel.IsCancellationRequested) return; _state = PortableTimerState.Waiting; } try { if (interval > TimeSpan.Zero) await Task.Delay(interval, _cancel.Token).ConfigureAwait(false); _state = PortableTimerState.Active; if (!_cancel.Token.IsCancellationRequested) { _onTick(_cancel.Token); } } catch (TaskCanceledException tcx) { SelfLog.WriteLine("The timer was canceled during invocation: {0}", tcx); } finally { lock (_stateLock) _state = PortableTimerState.NotWaiting; } }
public void Dispose() { _cancel.Cancel(); while (true) { lock (_stateLock) { if (_state == PortableTimerState.Disposed || _state == PortableTimerState.NotWaiting) { _state = PortableTimerState.Disposed; return; } } // On the very old platforms, we've got no option but to spin here. #if THREAD Thread.Sleep(10); #endif } }