|
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="RetrySafetyCounter.cs" company="Catel development team">
// Copyright (c) 2008 - 2011 Catel development team. All rights reserved.
// </copyright>
// <summary>
// Delegate to execute the work by the <see cref="RetrySafetyCounter" />.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Threading;
namespace Catel
{
#region Delegates
/// <summary>
/// Delegate to execute the work by the <see cref="RetrySafetyCounter"/>.
/// </summary>
/// <returns><c>true</c> if successful; otherwise <c>false</c>.</returns>
public delegate bool DoWorkDelegate();
/// <summary>
/// Delegate to check whether work is completed by the <see cref="RetrySafetyCounter"/>.
/// </summary>
/// <returns><c>true</c> if the work is completed; otherwise <c>false</c>.</returns>
public delegate bool IsWorkCompletedDelegate();
#endregion
/// <summary>
/// Class to use when an action should be retried for a specific amount of time, and between the retries, the thread must
/// sleep for a specific amount of time.
/// </summary>
/// <example>
/// <code>
/// int safetyCount = 25;
/// bool isSucceeded = false;
/// while ((isSucceeded != true) && (safetyCount > 0))
/// {
/// if (PerformAction())
/// {
/// isSucceeded = true;
/// }
///
/// safetyCount--;
/// }
/// </code>
/// </example>
public class RetrySafetyCounter
{
#region Variables
#endregion
#region Constructor & destructor
/// <summary>
/// Initializes a new instance of the <see cref="RetrySafetyCounter"/> class with a default of 25 retries and
/// a sleep time of 50 milliseconds.
/// </summary>
/// <param name="doWorkDelegate">The delegate that actually executes the work that should be done.</param>
/// <param name="isWorkCompletedDelegate">The delegate that checks whether the work is successful.</param>
/// <exception cref="ArgumentNullException">when <paramref name="doWorkDelegate"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException">when <paramref name="isWorkCompletedDelegate"/> is <c>null</c>.</exception>
public RetrySafetyCounter(DoWorkDelegate doWorkDelegate, IsWorkCompletedDelegate isWorkCompletedDelegate)
: this(doWorkDelegate, isWorkCompletedDelegate, 25)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RetrySafetyCounter"/> class with a sleep time of 50 milliseconds.
/// </summary>
/// <param name="doWorkDelegate">The delegate that actually executes the work that should be done.</param>
/// <param name="isWorkCompletedDelegate">The delegate that checks whether the work is successful.</param>
/// <param name="maximumNumberOfRetries">The number of retries.</param>
/// <exception cref="ArgumentNullException">when <paramref name="doWorkDelegate"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException">when <paramref name="isWorkCompletedDelegate"/> is <c>null</c>.</exception>
public RetrySafetyCounter(DoWorkDelegate doWorkDelegate, IsWorkCompletedDelegate isWorkCompletedDelegate, int maximumNumberOfRetries)
: this(doWorkDelegate, isWorkCompletedDelegate, maximumNumberOfRetries, 50)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RetrySafetyCounter"/> class.
/// </summary>
/// <param name="doWorkDelegate">The delegate that actually executes the work that should be done.</param>
/// <param name="isWorkCompletedDelegate">The delegate that checks whether the work is successful.</param>
/// <param name="maximumNumberOfRetries">The number of retries.</param>
/// <param name="millisecondsToSleep">The milliseconds to sleep.</param>
/// <exception cref="ArgumentNullException">when <paramref name="doWorkDelegate"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException">when <paramref name="isWorkCompletedDelegate"/> is <c>null</c>.</exception>
public RetrySafetyCounter(DoWorkDelegate doWorkDelegate, IsWorkCompletedDelegate isWorkCompletedDelegate,
int maximumNumberOfRetries, int millisecondsToSleep)
{
if (doWorkDelegate == null)
{
throw new ArgumentNullException("doWorkDelegate");
}
if (isWorkCompletedDelegate == null)
{
throw new ArgumentNullException("isWorkCompletedDelegate");
}
DoWorkDelegate = doWorkDelegate;
IsWorkCompletedDelegate = isWorkCompletedDelegate;
MaximumNumberOfRetries = maximumNumberOfRetries;
MillisecondsToSleep = millisecondsToSleep;
Reset();
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the delegate that actually executes the work that should be done.
/// </summary>
/// <value>The delegate.</value>
private DoWorkDelegate DoWorkDelegate { get; set; }
/// <summary>
/// Gets or sets the delegate that checks whether the work is successful.
/// </summary>
/// <value>The delegate.</value>
private IsWorkCompletedDelegate IsWorkCompletedDelegate { get; set; }
/// <summary>
/// Gets a value indicating whether this <see cref="RetrySafetyCounter"/> is successful.
/// </summary>
/// <value><c>true</c> if successful; otherwise, <c>false</c>.</value>
public bool IsSuccessful { get; private set; }
/// <summary>
/// Gets or sets the maximum number of retries.
/// </summary>
/// <value>The maximum number of retries.</value>
public int MaximumNumberOfRetries { get; set; }
/// <summary>
/// Gets the number of retries.
/// </summary>
/// <value>The number of retries.</value>
public int NumberOfRetries { get; private set; }
/// <summary>
/// Gets the number of retries left.
/// </summary>
/// <value>The number of retries left.</value>
public int NumberOfRetriesLeft { get; private set; }
/// <summary>
/// Gets or sets the milliseconds to sleep.
/// </summary>
/// <value>The milliseconds to sleep.</value>
public int MillisecondsToSleep { get; set; }
#endregion
#region Methods
/// <summary>
/// Executes the work that has to be performed in the while loop. If the <see cref="DoWorkDelegate"/>
/// returns <c>false</c> at any moment, the loop will be exited, even when number of retries left has not yet reached
/// zero.
/// </summary>
/// <returns><c>true</c> if succeeded; otherwise <c>false</c>.</returns>
public bool DoWork()
{
IsSuccessful = false;
while (NumberOfRetriesLeft > 0)
{
NumberOfRetriesLeft--;
NumberOfRetries++;
if (!DoWorkDelegate())
{
break;
}
if (IsWorkCompletedDelegate())
{
IsSuccessful = true;
break;
}
if (MillisecondsToSleep > 0)
{
Thread.Sleep(MillisecondsToSleep);
}
}
// A negative number would be dumb
if (NumberOfRetriesLeft < 0)
{
NumberOfRetriesLeft = 0;
}
return IsSuccessful;
}
/// <summary>
/// Resets the counter.
/// </summary>
public void Reset()
{
IsSuccessful = false;
NumberOfRetriesLeft = MaximumNumberOfRetries;
NumberOfRetries = 0;
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.