diff --git a/Nuclex.Windows.Forms.csproj b/Nuclex.Windows.Forms.csproj
index 7607c03..4e36029 100644
--- a/Nuclex.Windows.Forms.csproj
+++ b/Nuclex.Windows.Forms.csproj
@@ -101,6 +101,8 @@
ProgressReporterForm.cs
+ false
+ ProgressReporterForm.Designer
false
diff --git a/Source/AsyncProgressBar/AsyncProgressBar.cs b/Source/AsyncProgressBar/AsyncProgressBar.cs
index 607ceb8..aa299f2 100644
--- a/Source/AsyncProgressBar/AsyncProgressBar.cs
+++ b/Source/AsyncProgressBar/AsyncProgressBar.cs
@@ -73,6 +73,7 @@ namespace Nuclex.Windows.Forms {
/// Synchronously updates the value visualized in the progress bar
private void updateProgress() {
+ // Cache these to shorten the code that follows :)
int minimum = base.Minimum;
int maximum = base.Maximum;
diff --git a/Source/ProgressReporter/ProgressReporterForm.Designer.cs b/Source/ProgressReporter/ProgressReporterForm.Designer.cs
index 7768ada..746888b 100644
--- a/Source/ProgressReporter/ProgressReporterForm.Designer.cs
+++ b/Source/ProgressReporter/ProgressReporterForm.Designer.cs
@@ -25,7 +25,7 @@ namespace Nuclex.Windows.Forms {
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.cancelButton = new System.Windows.Forms.Button();
- this.progressBar = new System.Windows.Forms.ProgressBar();
+ this.progressBar = new Nuclex.Windows.Forms.AsyncProgressBar();
this.statusLabel = new System.Windows.Forms.Label();
this.controlCreationTimer = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
@@ -92,7 +92,7 @@ namespace Nuclex.Windows.Forms {
#endregion
private System.Windows.Forms.Button cancelButton;
- private System.Windows.Forms.ProgressBar progressBar;
+ private Nuclex.Windows.Forms.AsyncProgressBar progressBar;
private System.Windows.Forms.Label statusLabel;
private System.Windows.Forms.Timer controlCreationTimer;
}
diff --git a/Source/ProgressReporter/ProgressReporterForm.cs b/Source/ProgressReporter/ProgressReporterForm.cs
index 8016635..9077bd5 100644
--- a/Source/ProgressReporter/ProgressReporterForm.cs
+++ b/Source/ProgressReporter/ProgressReporterForm.cs
@@ -22,7 +22,6 @@ namespace Nuclex.Windows.Forms {
internal ProgressReporterForm() {
InitializeComponent();
- this.updateProgressDelegate = new MethodInvoker(updateProgress);
this.asyncEndedDelegate = new EventHandler(asyncEnded);
this.asyncProgressUpdatedDelegate = new EventHandler(
asyncProgressUpdated
@@ -112,8 +111,7 @@ namespace Nuclex.Windows.Forms {
// If the new state is 2, the form was ready to close (since the state
// is incremented once when the form becomes ready to be closed)
- int newState = Interlocked.Increment(ref this.state);
- if(newState == 2) {
+ if(Interlocked.Increment(ref this.state) == 2) {
// Close the dialog. Ensure the Close() method is invoked from the
// same thread the dialog was created in.
@@ -132,53 +130,7 @@ namespace Nuclex.Windows.Forms {
/// Contains the new progress achieved by the progression
///
private void asyncProgressUpdated(object sender, ProgressUpdateEventArgs arguments) {
-
- // Set the new progress without any synchronization
- this.currentProgress = arguments.Progress;
-
- // Another use of the double-checked locking idiom, here we're trying to optimize
- // away the lock in case some "trigger-happy" progressions send way more
- // progress updates than the poor control can process :)
- if(!this.progressUpdatePending) {
- lock(this) {
- if(!this.progressUpdatePending) {
- this.progressUpdatePending = true;
- this.progressUpdateAsyncResult = BeginInvoke(this.updateProgressDelegate);
- }
- } // lock
- }
-
- }
-
- /// Synchronously updates the value visualized in the progress bar
- private void updateProgress() {
- lock(this) {
-
- // Reset the update flag so incoming updates will cause the control to
- // update itself another time.
- this.progressUpdatePending = false;
- EndInvoke(this.progressUpdateAsyncResult);
-
- // Until the first progress event is received, the progress reporter shows
- // a marquee bar to entertain the user even when no progress reports are
- // being made at all.
- if(this.progressBar.Style == ProgressBarStyle.Marquee)
- this.progressBar.Style = ProgressBarStyle.Blocks;
-
- // Transform the progress into an integer in the range of the progress bar's
- // min and max values (these should normally be set to 0 and 100).
- int min = this.progressBar.Minimum;
- int max = this.progressBar.Maximum;
- int progress = (int)(this.currentProgress * (max - min)) + min;
-
- // Update the control
- this.progressBar.Value = Math.Min(Math.Max(progress, min), max);
-
- // Assigning the value sends PBM_SETPOS to the control which,
- // according to MSDN, already causes a redraw!
- //base.Invalidate();
-
- } // lock
+ this.progressBar.AsyncSetValue(arguments.Progress);
}
///
@@ -196,8 +148,7 @@ namespace Nuclex.Windows.Forms {
// If the new state is 2, then the form was requested to close before it had
// been fully constructed, so we should close it now!
- int newState = System.Threading.Interlocked.Increment(ref this.state);
- if(newState == 2)
+ if(Interlocked.Increment(ref this.state) == 2)
Close();
}
@@ -228,14 +179,6 @@ namespace Nuclex.Windows.Forms {
private EventHandler asyncEndedDelegate;
/// Delegate for the asyncProgressUpdated() method
private EventHandler asyncProgressUpdatedDelegate;
- /// Delegate for the progress update method
- private MethodInvoker updateProgressDelegate;
- /// Whether an update of the control state is pending
- private volatile bool progressUpdatePending;
- /// Async result for the invoked control state update method
- private volatile IAsyncResult progressUpdateAsyncResult;
- /// Most recently reported progress of the tracker
- private volatile float currentProgress;
/// Whether the form can be closed and should be closed
///
/// 0: Nothing happened yet
diff --git a/Source/TrackingBar/TrackingBar.cs b/Source/TrackingBar/TrackingBar.cs
index 21e4b33..c951435 100644
--- a/Source/TrackingBar/TrackingBar.cs
+++ b/Source/TrackingBar/TrackingBar.cs
@@ -32,7 +32,7 @@ using Nuclex.Support.Tracking;
namespace Nuclex.Windows.Forms {
/// Progress bar for tracking the progress of background operations
- public partial class TrackingBar : ProgressBar {
+ public partial class TrackingBar : AsyncProgressBar {
/// Initializes a new tracking bar
public TrackingBar() {
@@ -42,21 +42,20 @@ namespace Nuclex.Windows.Forms {
this.isIdle = true;
base.Visible = false;
+ // Create the tracker and attach ourselfes to its events
+ this.tracker = new ProgressionTracker();
+ this.tracker.AsyncIdleStateChanged += this.asyncIdleStateChangedDelegate;
+ this.tracker.AsyncProgressUpdated += this.asyncProgressUpdateDelegate;
+
// Initialize the delegates we use to update the control's state and those
// we use to register ourselfes to the tracker's events
this.updateIdleStateDelegate = new MethodInvoker(updateIdleState);
- this.updateProgressDelegate = new MethodInvoker(updateProgress);
this.asyncIdleStateChangedDelegate = new EventHandler(
asyncIdleStateChanged
);
this.asyncProgressUpdateDelegate = new EventHandler(
asyncProgressUpdated
);
-
- // Create the tracker and attach ourselfes to its events
- this.tracker = new ProgressionTracker();
- this.tracker.AsyncIdleStateChanged += this.asyncIdleStateChangedDelegate;
- this.tracker.AsyncProgressUpdated += this.asyncProgressUpdateDelegate;
}
/// Tracks the specified progression in the tracking bar
@@ -86,22 +85,7 @@ namespace Nuclex.Windows.Forms {
private void asyncProgressUpdated(
object sender, ProgressUpdateEventArgs arguments
) {
-
- // Set the new progress without any synchronization
- this.currentProgress = arguments.Progress;
-
- // Another use of the double-checked locking idiom, here we're trying to optimize
- // away the lock in case some "trigger-happy" progressions send way more
- // progress updates than the poor control can process :)
- if(!this.progressUpdatePending) {
- lock(this) {
- if(!this.progressUpdatePending) {
- this.progressUpdatePending = true;
- this.progressUpdateAsyncResult = BeginInvoke(this.updateProgressDelegate);
- }
- } // lock
- }
-
+ AsyncSetValue(arguments.Progress);
}
/// Called when the tracker becomes enters of leaves the idle state
@@ -113,33 +97,13 @@ namespace Nuclex.Windows.Forms {
// lost because otherwise, the progress bar might stay on-screen when in fact,
// the background operation has already finished and nothing is happening anymore.
this.isIdle = arguments.Idle;
- Invoke(this.updateIdleStateDelegate);
- }
+ // Update the bar's idle state
+ if(InvokeRequired)
+ Invoke(this.updateIdleStateDelegate);
+ else
+ updateIdleState();
- /// Synchronously updates the value visualized in the progress bar
- private void updateProgress() {
- lock(this) {
-
- // Reset the update flag so incoming updates will cause the control to
- // update itself another time.
- this.progressUpdatePending = false;
- EndInvoke(this.progressUpdateAsyncResult);
-
- // Transform the progress into an integer in the range of the progress bar's
- // min and max values (these should normally be set to 0 and 100).
- int min = base.Minimum;
- int max = base.Maximum;
- int progress = (int)(this.currentProgress * (max - min)) + min;
-
- // Update the control
- base.Value = progress;
-
- // Assigning the value sends PBM_SETPOS to the control which,
- // according to MSDN, already causes a redraw!
- //base.Invalidate();
-
- } // lock
}
///
@@ -148,23 +112,15 @@ namespace Nuclex.Windows.Forms {
///
private void updateIdleState() {
+ // Only show the progress bar when something is happening
base.Visible = !this.isIdle;
}
- /// Whether an update of the control state is pending
- private volatile bool progressUpdatePending;
- /// Async result for the invoked control state update method
- private volatile IAsyncResult progressUpdateAsyncResult;
/// Whether the progress bar is in the idle state
private volatile bool isIdle;
- /// Most recently reported progress of the tracker
- private volatile float currentProgress;
-
/// Tracker used to sum and update the total progress
private ProgressionTracker tracker;
- /// Delegate for the progress update method
- private MethodInvoker updateProgressDelegate;
/// Delegate for the idle state update method
private MethodInvoker updateIdleStateDelegate;
/// Delegate for the OnAsyncProgressionEnded method