Renamed ProgressUpdated event to ProgressChanged in order to conform with the status report naming convention; removed progress reporting from the Progression class; moved progress reporting into its own interface which is now optional to implement for any background task; renamed Progression to Waitable since it no longer has anything to do with progress; fixed unit tests

git-svn-id: file:///srv/devel/repo-conversion/nusu@64 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2008-03-26 21:03:49 +00:00
parent 1161ef8f25
commit 7dbfc3c422
15 changed files with 321 additions and 160 deletions

View file

@ -43,7 +43,7 @@ namespace Nuclex.Support.Scheduling {
/// <summary>Called when the queue operations's progress changes</summary>
/// <param name="sender">Queue operation whose progress has changed</param>
/// <param name="e">Contains the new progress achieved</param>
void ProgressUpdated(object sender, ProgressUpdateEventArgs e);
void ProgressChanged(object sender, ProgressReportEventArgs e);
/// <summary>Called when the queue operation has ended</summary>
/// <param name="sender">Queue operation that as ended</param>
@ -61,7 +61,7 @@ namespace Nuclex.Support.Scheduling {
/// <summary>Initializes a new ProgressUpdateEventArgsMatcher </summary>
/// <param name="expected">Expected progress update event arguments</param>
public ProgressUpdateEventArgsMatcher(ProgressUpdateEventArgs expected) {
public ProgressUpdateEventArgsMatcher(ProgressReportEventArgs expected) {
this.expected = expected;
}
@ -73,7 +73,7 @@ namespace Nuclex.Support.Scheduling {
/// True if the actual value matches the expected value; otherwise false
/// </returns>
public override bool Matches(object actualAsObject) {
ProgressUpdateEventArgs actual = (actualAsObject as ProgressUpdateEventArgs);
ProgressReportEventArgs actual = (actualAsObject as ProgressReportEventArgs);
if(actual == null)
return false;
@ -87,7 +87,7 @@ namespace Nuclex.Support.Scheduling {
}
/// <summary>Expected progress update event args value</summary>
private ProgressUpdateEventArgs expected;
private ProgressReportEventArgs expected;
}
@ -96,7 +96,10 @@ namespace Nuclex.Support.Scheduling {
#region class TestOperation
/// <summary>Progression used for testing in this unit test</summary>
private class TestOperation : Operation {
private class TestOperation : Operation, IProgressReporter {
/// <summary>will be triggered to report when progress has been achieved</summary>
public event EventHandler<ProgressReportEventArgs> AsyncProgressChanged;
/// <summary>Begins executing the operation. Yeah, sure :)</summary>
public override void Start() { }
@ -118,7 +121,7 @@ namespace Nuclex.Support.Scheduling {
/// New progress to be reported by the testing progression
/// </param>
public void ChangeProgress(float progress) {
OnAsyncProgressUpdated(progress);
OnAsyncProgressChanged(progress);
}
/// <summary>
@ -130,6 +133,29 @@ namespace Nuclex.Support.Scheduling {
throw this.exception;
}
/// <summary>Fires the progress update event</summary>
/// <param name="progress">Progress to report (ranging from 0.0 to 1.0)</param>
/// <remarks>
/// Informs the observers of this progression about the achieved progress.
/// </remarks>
protected virtual void OnAsyncProgressChanged(float progress) {
OnAsyncProgressChanged(new ProgressReportEventArgs(progress));
}
/// <summary>Fires the progress update event</summary>
/// <param name="eventArguments">Progress to report (ranging from 0.0 to 1.0)</param>
/// <remarks>
/// Informs the observers of this progression about the achieved progress.
/// Allows for classes derived from the Progression class to easily provide
/// a custom event arguments class that has been derived from the
/// Progression's ProgressUpdateEventArgs class.
/// </remarks>
protected virtual void OnAsyncProgressChanged(ProgressReportEventArgs eventArguments) {
EventHandler<ProgressReportEventArgs> copy = AsyncProgressChanged;
if(copy != null)
copy(this, eventArguments);
}
/// <summary>Exception that has occured in the background process</summary>
private volatile Exception exception;
@ -159,22 +185,22 @@ namespace Nuclex.Support.Scheduling {
testQueueOperation.Start();
Expect.Once.On(mockedSubscriber).
Method("ProgressUpdated").
Method("ProgressChanged").
With(
new Matcher[] {
new NMock2.Matchers.TypeMatcher(typeof(QueueOperation<TestOperation>)),
new ProgressUpdateEventArgsMatcher(new ProgressUpdateEventArgs(0.25f))
new ProgressUpdateEventArgsMatcher(new ProgressReportEventArgs(0.25f))
}
);
operation1.ChangeProgress(0.5f);
Expect.Once.On(mockedSubscriber).
Method("ProgressUpdated").
Method("ProgressChanged").
With(
new Matcher[] {
new NMock2.Matchers.TypeMatcher(typeof(QueueOperation<TestOperation>)),
new ProgressUpdateEventArgsMatcher(new ProgressUpdateEventArgs(0.5f))
new ProgressUpdateEventArgsMatcher(new ProgressReportEventArgs(0.5f))
}
);
@ -191,8 +217,8 @@ namespace Nuclex.Support.Scheduling {
this.mockery.NewMock<IQueueOperationSubscriber>();
operation.AsyncEnded += new EventHandler(mockedSubscriber.Ended);
operation.AsyncProgressUpdated +=
new EventHandler<ProgressUpdateEventArgs>(mockedSubscriber.ProgressUpdated);
(operation as IProgressReporter).AsyncProgressChanged +=
new EventHandler<ProgressReportEventArgs>(mockedSubscriber.ProgressChanged);
return mockedSubscriber;
}

View file

@ -32,15 +32,8 @@ namespace Nuclex.Support.Scheduling {
public class QueueOperation<OperationType> : Operation
where OperationType : Operation {
/// <summary>Initializes a new queue operation</summary>
private QueueOperation() {
this.asyncOperationEndedDelegate = new EventHandler(asyncOperationEnded);
this.asyncOperationProgressUpdatedDelegate = new EventHandler<ProgressUpdateEventArgs>(
asyncOperationProgressUpdated
);
this.children = new List<WeightedProgression<OperationType>>();
}
/// <summary>will be triggered to report when progress has been achieved</summary>
public event EventHandler<ProgressReportEventArgs> AsyncProgressUpdated;
/// <summary>Initializes a new queue operation with default weights</summary>
/// <param name="childs">Child operations to execute in this operation</param>
@ -74,6 +67,16 @@ namespace Nuclex.Support.Scheduling {
}
/// <summary>Initializes a new queue operation</summary>
private QueueOperation() {
this.asyncOperationEndedDelegate = new EventHandler(asyncOperationEnded);
this.asyncOperationProgressChangedDelegate = new EventHandler<ProgressReportEventArgs>(
asyncOperationProgressChanged
);
this.children = new List<WeightedProgression<OperationType>>();
}
/// <summary>Provides access to the child operations of this queue</summary>
public IList<WeightedProgression<OperationType>> Children {
get { return this.children; }
@ -93,6 +96,29 @@ namespace Nuclex.Support.Scheduling {
throw this.exception;
}
/// <summary>Fires the progress update event</summary>
/// <param name="progress">Progress to report (ranging from 0.0 to 1.0)</param>
/// <remarks>
/// Informs the observers of this progression about the achieved progress.
/// </remarks>
protected virtual void OnAsyncProgressChanged(float progress) {
OnAsyncProgressChanged(new ProgressReportEventArgs(progress));
}
/// <summary>Fires the progress update event</summary>
/// <param name="eventArguments">Progress to report (ranging from 0.0 to 1.0)</param>
/// <remarks>
/// Informs the observers of this progression about the achieved progress.
/// Allows for classes derived from the Progression class to easily provide
/// a custom event arguments class that has been derived from the
/// Progression's ProgressUpdateEventArgs class.
/// </remarks>
protected virtual void OnAsyncProgressChanged(ProgressReportEventArgs eventArguments) {
EventHandler<ProgressReportEventArgs> copy = AsyncProgressUpdated;
if(copy != null)
copy(this, eventArguments);
}
/// <summary>Prepares the current operation and calls its Begin() method</summary>
/// <remarks>
/// This subscribes the queue to the events of to the current operation
@ -102,7 +128,10 @@ namespace Nuclex.Support.Scheduling {
OperationType operation = this.children[this.currentOperationIndex].Progression;
operation.AsyncEnded += this.asyncOperationEndedDelegate;
operation.AsyncProgressUpdated += this.asyncOperationProgressUpdatedDelegate;
IProgressReporter progressReporter = operation as IProgressReporter;
if(progressReporter != null)
progressReporter.AsyncProgressChanged += this.asyncOperationProgressChangedDelegate;
operation.Start();
}
@ -118,7 +147,10 @@ namespace Nuclex.Support.Scheduling {
// Disconnect from the operation's events
operation.AsyncEnded -= this.asyncOperationEndedDelegate;
operation.AsyncProgressUpdated -= this.asyncOperationProgressUpdatedDelegate;
IProgressReporter progressReporter = operation as IProgressReporter;
if(progressReporter != null)
progressReporter.AsyncProgressChanged -= this.asyncOperationProgressChangedDelegate;
try {
operation.Join();
@ -127,7 +159,7 @@ namespace Nuclex.Support.Scheduling {
this.completedWeight += this.children[this.currentOperationIndex].Weight;
// Trigger another progress update
OnAsyncProgressUpdated(this.completedWeight / this.totalWeight);
OnAsyncProgressChanged(this.completedWeight / this.totalWeight);
}
catch(Exception exception) {
this.exception = exception;
@ -165,7 +197,7 @@ namespace Nuclex.Support.Scheduling {
/// <summary>Called when currently executing operation makes progress</summary>
/// <param name="sender">Operation that has achieved progress</param>
/// <param name="e">Not used</param>
private void asyncOperationProgressUpdated(object sender, ProgressUpdateEventArgs e) {
private void asyncOperationProgressChanged(object sender, ProgressReportEventArgs e) {
// Determine the completed weight of the currently executing operation
float currentOperationCompletedWeight =
@ -176,14 +208,14 @@ namespace Nuclex.Support.Scheduling {
(this.completedWeight + currentOperationCompletedWeight) / this.totalWeight;
// Done, we can send the actual progress to any event subscribers
OnAsyncProgressUpdated(progress);
OnAsyncProgressChanged(progress);
}
/// <summary>Delegate to the asyncOperationEnded() method</summary>
private EventHandler asyncOperationEndedDelegate;
/// <summary>Delegate to the asyncOperationProgressUpdated() method</summary>
private EventHandler<ProgressUpdateEventArgs> asyncOperationProgressUpdatedDelegate;
private EventHandler<ProgressReportEventArgs> asyncOperationProgressChangedDelegate;
/// <summary>Operations being managed in the queue</summary>
private List<WeightedProgression<OperationType>> children;
/// <summary>Summed weight of all operations in the queue</summary>