#region Copyright 2010-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System;
using System.Diagnostics;
using System.Timers;
// ReSharper disable EmptyGeneralCatchClause
namespace CSharpTest.Net.Delegates
{
///
/// Provides scheduling a single-fire event at some duration into the future. The operation is
/// performed once either when the duration expires, or when this object is disposed or collected.
///
public class TimeoutAction : IDisposable
{
private Action _onerror;
private Action _perform;
private readonly Timer _timer;
///
/// Provides scheduling a single-fire event at some duration into the future. The operation is
/// performed once either when the duration expires, or when this object is disposed or collected.
///
public TimeoutAction(TimeSpan wait, Action perform)
: this(wait, perform, TraceException)
{
}
///
/// Provides scheduling a single-fire event at some duration into the future. The operation is
/// performed once either when the duration expires, or when this object is disposed or collected.
///
public TimeoutAction(TimeSpan wait, Action perform, Action onerror)
{
_perform = perform;
_onerror = onerror;
_timer = new Timer();
_timer.BeginInit();
_timer.AutoReset = false;
_timer.Elapsed += TimerElapsed;
_timer.Interval = wait.TotalMilliseconds;
_timer.EndInit();
_timer.Start();
}
/// Fires if the event if needed and closes the object
~TimeoutAction() { Dispose(false); }
/// Fires if the event if needed and closes the object
public void Dispose() { _timer.Stop(); Dispose(true); }
/// Fires if the event if needed and closes the object
protected virtual void Dispose(bool disposing)
{
lock (this)
{
try
{
_perform();
}
catch (Exception ex)
{
try { _onerror(ex); }
catch { }
}
finally
{
_perform = Ignore;
_onerror = TraceException;
if (disposing)
{
GC.SuppressFinalize(this);
_timer.Dispose();
}
}
}
}
private static void Ignore() { }
private void TimerElapsed(object sender, EventArgs e)
{
Dispose();
}
private static void TraceException(Exception ex)
{
Trace.WriteLine(ex, typeof(TimeoutAction).FullName);
}
/// Enqueues a task to be performed at some time in the future
public static TimeoutAction Start(TimeSpan wait, Action perform)
{
return Start(wait, perform, TraceException);
}
/// Enqueues a task to be performed at some time in the future
public static TimeoutAction Start(TimeSpan wait, Action perform, Action onerror)
{
return new TimeoutAction(wait, perform, onerror);
}
/// Enqueues a task to be performed at some time in the future
public static TimeoutAction Start(TimeSpan wait, Action perform, T1 arg1)
{
return Start(wait, perform, arg1, TraceException);
}
/// Enqueues a task to be performed at some time in the future
public static TimeoutAction Start(TimeSpan wait, Action perform, T1 arg1, Action onerror)
{
return Start(wait, delegate() { perform(arg1); }, onerror);
}
}
}