##// END OF EJS Templates
Fixed promise rejection when there is not specified error handler in the reaction....
Fixed promise rejection when there is not specified error handler in the reaction. FIXED SPELLING IN THE XML CONTAINER CONFIGURATION signleton->singleton Code cleanup Update tests make them working on dotnet core

File last commit:

r289:95896f882995 v3.0.14 v3
r295:28af686e24f7 default
Show More
PollingComponent.cs
106 lines | 3.3 KiB | text/x-csharp | CSharpLexer
cin
Added tests for Implab.ServiceHost.Unity configuration loader.
r289 using System;
using System.Threading;
using System.Threading.Tasks;
namespace Implab.Components {
public abstract class PollingComponent : RunnableComponent {
readonly Timer m_timer;
readonly CancellationTokenSource m_cancellation = new CancellationTokenSource();
Task m_pending;
Task m_poll;
/// <summary>
/// Poll interval in milliseconds.
/// </summary>
/// <returns></returns>
public int Interval { get; set; }
/// <summary>
/// Delay to the first poll after start in milliseconds
/// </summary>
/// <returns></returns>
public int Delay { get; set; }
/// <summary>
/// Indicates how to handle unhandled exceptions in <see cref="Poll()"/> method.
/// </summary>
/// <returns></returns>
public bool FailOnError { get; set; }
/// <summary>
/// Event for the unhandled exceptions in <see cref="Poll()"/> method.
/// </summary>
public event EventHandler<UnhandledExceptionEventArgs> UnhandledException;
protected PollingComponent(bool initialized) : base(initialized) {
m_timer = new Timer(OnTimer);
}
protected override void RunInternal() {
ScheduleNextPoll(Delay);
}
protected override async Task StopInternalAsync(CancellationToken ct) {
// component in Stopping state, no new polls will be scheduled
// we do not need additional synchronization logic here
// since RunnableComponent already done this
m_cancellation.Cancel();
try {
// await for pending poll
if (m_poll != null)
await m_poll;
} catch (OperationCanceledException) {
// OK
}
}
protected abstract Task Poll(CancellationToken ct);
void ScheduleNextPoll(int timeout) {
// access and modification of the component state
// in custom methods requires a synchronization
lock (SynchronizationObject) {
if (State == ExecutionState.Running) {
m_pending = Safe.CreateTask(m_cancellation.Token);
m_poll = m_pending.Then(() => Poll(m_cancellation.Token));
m_timer.Change(timeout, Timeout.Infinite);
}
}
}
async void OnTimer(object state) {
try {
// changes to m_pending and m_poll are done
// only in ScheduleNextPoll method, hence we
// can safely use them here
m_pending.Start();
await m_poll;
// schedule next poll
ScheduleNextPoll(Interval);
} catch (Exception e) {
// hanle error
UnhandledException.DispatchEvent(this, new UnhandledExceptionEventArgs(e, false));
if (FailOnError)
Fail(e);
else
ScheduleNextPoll(Interval);
}
}
protected override void Dispose(bool disposing) {
if (disposing)
Safe.Dispose(m_timer, m_cancellation);
base.Dispose(disposing);
}
}
}