Return to Snippet

Revision: 28291
at August 9, 2010 08:40 by jimfred


Updated Code
// Example usage:
      private void button4_Click(object sender, EventArgs e)
      {
         // Create dialog.
         ProgressWithCancel dlgProgress = new ProgressWithCancel( "Testing progress", LongOperation);

         // Show dialog with Synchronous/blocking call.
         // LongOperation() is called by dialog.
         dlgProgress.ShowDialog(); // Synchronous/blocking call.
      }

      private void LongOperation(object sender, DoWorkEventArgs e)
      {
         BackgroundWorker worker = sender as BackgroundWorker;

         int max = 20;
         for (int i = 0; i < max; i++)
         {
            if (worker.CancellationPending) // See if cacel button was pressed.
            {
               System.Threading.Thread.Sleep(2000); // Similate time for clean-up.
               break;
            }
            
            int percent = i * 100 / max;

            string userState = percent.ToString(); // render a string to display on the progress dialog.

            // Append to string just to show multi-line user-status info.
            if (percent >= 45 && percent <= 55) { userState += "Half way"; }
            if (percent >= 85) { userState += "Almost done"; }

            worker.ReportProgress(percent, userState); // Report percent and user-status info to dialog.

            System.Threading.Thread.Sleep(800); // Simulate time-consuming operation
         }
      }


// Implementation (in ProgressWithCancel.cs)

namespace ProgressWithCancel
{
   public partial class ProgressWithCancel : Form
   {
      public ProgressWithCancel(string whyWeAreWaiting, DoWorkEventHandler work)
      {
         InitializeComponent();
         this.Text = whyWeAreWaiting; // Show in title bar
         backgroundWorker1.DoWork += work; // Event handler to be called in context of new thread.
      }

      private void btnCancel_Click(object sender, EventArgs e)
      {
         label1.Text = "Cancel pending";
         backgroundWorker1.CancelAsync(); // Tell worker to abort.
         btnCancel.Enabled = false;
      }

      private void Progress_Load(object sender, EventArgs e)
      {
         backgroundWorker1.RunWorkerAsync();
      }

      private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
      {
         progressBar1.Value = e.ProgressPercentage;
         label1.Text = e.UserState as string;
      }

      private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
         Close();
      }

   }
}


// Designer (in ProgressWithCancel.designer.cs)
namespace ProgressWithCancel
{
   partial class ProgressWithCancel
   {
      /// <summary>
      /// Required designer variable.
      /// </summary>
      private System.ComponentModel.IContainer components = null;

      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
      protected override void Dispose(bool disposing)
      {
         if (disposing && (components != null))
         {
            components.Dispose();
         }
         base.Dispose(disposing);
      }

      #region Windows Form Designer generated code

      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {
         this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
         this.btnCancel = new System.Windows.Forms.Button();
         this.progressBar1 = new System.Windows.Forms.ProgressBar();
         this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
         this.label1 = new System.Windows.Forms.Label();
         this.tableLayoutPanel1.SuspendLayout();
         this.SuspendLayout();
         // 
         // tableLayoutPanel1
         // 
         this.tableLayoutPanel1.AutoSize = true;
         this.tableLayoutPanel1.ColumnCount = 1;
         this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
         this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);
         this.tableLayoutPanel1.Controls.Add(this.btnCancel, 0, 2);
         this.tableLayoutPanel1.Controls.Add(this.progressBar1, 0, 1);
         this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
         this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
         this.tableLayoutPanel1.Name = "tableLayoutPanel1";
         this.tableLayoutPanel1.RowCount = 3;
         this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
         this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
         this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
         this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
         this.tableLayoutPanel1.Size = new System.Drawing.Size(292, 99);
         this.tableLayoutPanel1.TabIndex = 0;
         // 
         // btnCancel
         // 
         this.btnCancel.Anchor = System.Windows.Forms.AnchorStyles.Top;
         this.btnCancel.AutoSize = true;
         this.btnCancel.Location = new System.Drawing.Point(108, 60);
         this.btnCancel.Name = "btnCancel";
         this.btnCancel.Size = new System.Drawing.Size(75, 27);
         this.btnCancel.TabIndex = 0;
         this.btnCancel.Text = "Cancel";
         this.btnCancel.UseVisualStyleBackColor = true;
         this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
         // 
         // progressBar1
         // 
         this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
         this.progressBar1.Location = new System.Drawing.Point(3, 34);
         this.progressBar1.Name = "progressBar1";
         this.progressBar1.Size = new System.Drawing.Size(286, 20);
         this.progressBar1.TabIndex = 1;
         // 
         // backgroundWorker1
         // 
         this.backgroundWorker1.WorkerReportsProgress = true;
         this.backgroundWorker1.WorkerSupportsCancellation = true;
         this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
         this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
         // 
         // label1
         // 
         this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                     | System.Windows.Forms.AnchorStyles.Left)
                     | System.Windows.Forms.AnchorStyles.Right)));
         this.label1.AutoSize = true;
         this.label1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
         this.label1.Location = new System.Drawing.Point(3, 3);
         this.label1.Margin = new System.Windows.Forms.Padding(3);
         this.label1.Name = "label1";
         this.label1.Padding = new System.Windows.Forms.Padding(3);
         this.label1.Size = new System.Drawing.Size(286, 25);
         this.label1.TabIndex = 1;
         this.label1.Text = "label1";
         this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
         // 
         // Progress
         // 
         this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
         this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
         this.AutoSize = true;
         this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
         this.ClientSize = new System.Drawing.Size(292, 99);
         this.ControlBox = false;
         this.Controls.Add(this.tableLayoutPanel1);
         this.Name = "Progress";
         this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
         this.Text = "Progress";
         this.Load += new System.EventHandler(this.Progress_Load);
         this.tableLayoutPanel1.ResumeLayout(false);
         this.tableLayoutPanel1.PerformLayout();
         this.ResumeLayout(false);
         this.PerformLayout();

      }

      #endregion

      private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
      private System.Windows.Forms.Button btnCancel;
      public System.Windows.Forms.ProgressBar progressBar1;
      public System.ComponentModel.BackgroundWorker backgroundWorker1;
      private System.Windows.Forms.Label label1;
   }
}

Revision: 28290
at July 6, 2010 13:27 by jimfred


Updated Code
// Example usage:
      private void button4_Click(object sender, EventArgs e)
      {
         ProgressWithCancel dlgProgress = new ProgressWithCancel( "Testing progress", LongOperation);
         dlgProgress.ShowDialog(); // Synchronous/blocking call.
      }

      private void LongOperation(object sender, DoWorkEventArgs e)
      {
         BackgroundWorker worker = sender as BackgroundWorker;

         int max = 20;
         for (int i = 0; i < max; i++)
         {
            if (worker.CancellationPending) // See if cacel button was pressed.
            {
               System.Threading.Thread.Sleep(2000); // Similate time for clean-up.
               break;
            }
            
            int percent = i * 100 / max;

            string userState = percent.ToString(); // render a string to display on the progress dialog.

            // Append to string just to show multi-line user-status info.
            if (percent >= 45 && percent <= 55) { userState += "
Half way"; }
            if (percent >= 85) { userState += "
Almost done"; }

            worker.ReportProgress(percent, userState); // Report percent and user-status info to dialog.

            System.Threading.Thread.Sleep(800); // Simulate time-consuming operation
         }
      }


// Implementation


namespace ProgressWithCancel
{
   public partial class ProgressWithCancel : Form
   {
      public ProgressWithCancel(string whyWeAreWaiting, DoWorkEventHandler work)
      {
         InitializeComponent();
         this.Text = whyWeAreWaiting; // Show in title bar
         backgroundWorker1.DoWork += work; // Event handler to be called in context of new thread.
      }

      private void btnCancel_Click(object sender, EventArgs e)
      {
         label1.Text = "Cancel pending";
         backgroundWorker1.CancelAsync(); // Tell worker to abort.
         btnCancel.Enabled = false;
      }

      private void Progress_Load(object sender, EventArgs e)
      {
         backgroundWorker1.RunWorkerAsync();
      }

      private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
      {
         progressBar1.Value = e.ProgressPercentage;
         label1.Text = e.UserState as string;
      }

      private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
         Close();
      }

   }
}


// Designer
namespace ProgressWithCancel
{
   partial class ProgressWithCancel
   {
      /// <summary>
      /// Required designer variable.
      /// </summary>
      private System.ComponentModel.IContainer components = null;

      /// <summary>
      /// Clean up any resources being used.
      /// </summary>
      /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
      protected override void Dispose(bool disposing)
      {
         if (disposing && (components != null))
         {
            components.Dispose();
         }
         base.Dispose(disposing);
      }

      #region Windows Form Designer generated code

      /// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      private void InitializeComponent()
      {
         this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
         this.btnCancel = new System.Windows.Forms.Button();
         this.progressBar1 = new System.Windows.Forms.ProgressBar();
         this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
         this.label1 = new System.Windows.Forms.Label();
         this.tableLayoutPanel1.SuspendLayout();
         this.SuspendLayout();
         // 
         // tableLayoutPanel1
         // 
         this.tableLayoutPanel1.AutoSize = true;
         this.tableLayoutPanel1.ColumnCount = 1;
         this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
         this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0);
         this.tableLayoutPanel1.Controls.Add(this.btnCancel, 0, 2);
         this.tableLayoutPanel1.Controls.Add(this.progressBar1, 0, 1);
         this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
         this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
         this.tableLayoutPanel1.Name = "tableLayoutPanel1";
         this.tableLayoutPanel1.RowCount = 3;
         this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
         this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
         this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
         this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
         this.tableLayoutPanel1.Size = new System.Drawing.Size(292, 99);
         this.tableLayoutPanel1.TabIndex = 0;
         // 
         // btnCancel
         // 
         this.btnCancel.Anchor = System.Windows.Forms.AnchorStyles.Top;
         this.btnCancel.AutoSize = true;
         this.btnCancel.Location = new System.Drawing.Point(108, 60);
         this.btnCancel.Name = "btnCancel";
         this.btnCancel.Size = new System.Drawing.Size(75, 27);
         this.btnCancel.TabIndex = 0;
         this.btnCancel.Text = "Cancel";
         this.btnCancel.UseVisualStyleBackColor = true;
         this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
         // 
         // progressBar1
         // 
         this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
         this.progressBar1.Location = new System.Drawing.Point(3, 34);
         this.progressBar1.Name = "progressBar1";
         this.progressBar1.Size = new System.Drawing.Size(286, 20);
         this.progressBar1.TabIndex = 1;
         // 
         // backgroundWorker1
         // 
         this.backgroundWorker1.WorkerReportsProgress = true;
         this.backgroundWorker1.WorkerSupportsCancellation = true;
         this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
         this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
         // 
         // label1
         // 
         this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                     | System.Windows.Forms.AnchorStyles.Left)
                     | System.Windows.Forms.AnchorStyles.Right)));
         this.label1.AutoSize = true;
         this.label1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
         this.label1.Location = new System.Drawing.Point(3, 3);
         this.label1.Margin = new System.Windows.Forms.Padding(3);
         this.label1.Name = "label1";
         this.label1.Padding = new System.Windows.Forms.Padding(3);
         this.label1.Size = new System.Drawing.Size(286, 25);
         this.label1.TabIndex = 1;
         this.label1.Text = "label1";
         this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
         // 
         // Progress
         // 
         this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
         this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
         this.AutoSize = true;
         this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
         this.ClientSize = new System.Drawing.Size(292, 99);
         this.ControlBox = false;
         this.Controls.Add(this.tableLayoutPanel1);
         this.Name = "Progress";
         this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
         this.Text = "Progress";
         this.Load += new System.EventHandler(this.Progress_Load);
         this.tableLayoutPanel1.ResumeLayout(false);
         this.tableLayoutPanel1.PerformLayout();
         this.ResumeLayout(false);
         this.PerformLayout();

      }

      #endregion

      private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
      private System.Windows.Forms.Button btnCancel;
      public System.Windows.Forms.ProgressBar progressBar1;
      public System.ComponentModel.BackgroundWorker backgroundWorker1;
      private System.Windows.Forms.Label label1;
   }
}

Revision: 28289
at July 6, 2010 13:23 by jimfred


Initial Code
a

Initial URL


Initial Description
Features/Requirements:\r\n\r\n[1] lightweight, easy-to-add\r\n[2] Display progress of long operation using (a) progress bar and (b) user-text.\r\n[3] Close dialog upon (a) Normal completion of long operation or (b) Cancel button used for early cancellation of long operation\r\n[4] GUI not hung/hourglassing during long operation. This can be done using threads or DoEvents. This example uses the BackgroundWorker class as a member of a Form.\r\n[5] Synchronized with no race conditions.\r\n\r\nThe form displayed consists of three elements: label, progress bar and a cancel button.  The label auto-sizes so that user text will be displayed.  The application constructs the dialog with parameters for titlebar text and a delegate for the long operation. The long operation reports progress using BackgroundWorker.ReportProgress. The long operation checks for cancellation using BackgroundWorker.CancellationPending\r\n\r\nSee code for example usage.

Initial Title
Modal Progress dialog with cancel for time-consuming operations, C#, WinForms

Initial Tags


Initial Language
C#