diff --git a/Source/Scheduling/OperationQueue.Test.cs b/Source/Scheduling/OperationQueue.Test.cs
index 3dd160f..9aeab79 100644
--- a/Source/Scheduling/OperationQueue.Test.cs
+++ b/Source/Scheduling/OperationQueue.Test.cs
@@ -18,12 +18,12 @@ License along with this library
*/
#endregion
+#if UNITTEST
+
using System;
using System.Collections.Generic;
using System.IO;
-#if UNITTEST
-
using NUnit.Framework;
using NMock2;
@@ -354,6 +354,7 @@ namespace Nuclex.Support.Scheduling {
/// Mock object factory
private Mockery mockery;
+
}
} // namespace Nuclex.Support.Tracking
diff --git a/Source/Scheduling/OperationQueue.cs b/Source/Scheduling/OperationQueue.cs
index 7155fc5..3b9a896 100644
--- a/Source/Scheduling/OperationQueue.cs
+++ b/Source/Scheduling/OperationQueue.cs
@@ -20,6 +20,7 @@ License along with this library
using System;
using System.Collections.Generic;
+using System.Threading;
using Nuclex.Support.Tracking;
@@ -125,24 +126,29 @@ namespace Nuclex.Support.Scheduling {
/// and launches the operation by calling its Start() method.
///
private void startCurrentOperation() {
- OperationType operation = this.children[this.currentOperationIndex].Transaction;
+ do {
+ Thread.MemoryBarrier();
+ OperationType operation = this.children[this.currentOperationIndex].Transaction;
- operation.AsyncEnded += this.asyncOperationEndedDelegate;
+ operation.AsyncEnded += this.asyncOperationEndedDelegate;
- IProgressReporter progressReporter = operation as IProgressReporter;
- if(progressReporter != null)
- progressReporter.AsyncProgressChanged += this.asyncOperationProgressChangedDelegate;
+ IProgressReporter progressReporter = operation as IProgressReporter;
+ if(progressReporter != null)
+ progressReporter.AsyncProgressChanged += this.asyncOperationProgressChangedDelegate;
- operation.Start();
+ Interlocked.Exchange(ref this.completionStatus, 1);
+ operation.Start();
+ } while(Interlocked.Decrement(ref this.completionStatus) > 0);
}
/// Disconnects from the current operation and calls its End() method
///
/// This unsubscribes the queue from the current operation's events, calls End()
/// on the operation and, if the operation didn't have an exception to report,
- /// counts up the accumulated progress of the queue.
+ /// counts up the accumulated progress of th e queue.
///
private void endCurrentOperation() {
+ Thread.MemoryBarrier();
OperationType operation = this.children[this.currentOperationIndex].Transaction;
// Disconnect from the operation's events
@@ -177,15 +183,16 @@ namespace Nuclex.Support.Scheduling {
// Only jump to the next operation if no exception occured
if(this.exception == null) {
-
- ++this.currentOperationIndex;
+ int newIndex = Interlocked.Increment(ref this.currentOperationIndex);
+ Thread.MemoryBarrier();
// Execute the next operation unless we reached the end of the queue
- if(this.currentOperationIndex < this.children.Count) {
- startCurrentOperation();
+ if(newIndex < this.children.Count) {
+ if(Interlocked.Increment(ref this.completionStatus) == 1) {
+ startCurrentOperation();
+ }
return;
}
-
}
// Either an exception has occured or we reached the end of the operation
@@ -225,6 +232,8 @@ namespace Nuclex.Support.Scheduling {
private float completedWeight;
/// Index of the operation currently executing
private int currentOperationIndex;
+ /// Used to detect when an operation completes synchronously
+ private int completionStatus;
/// Exception that has occured in the background process
private volatile Exception exception;