Results 1 to 2 of 2

Thread: Modal Wait Dialogue with BackgroundWorker

  1. #1

    Thread Starter
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    105,579

    Modal Wait Dialogue with BackgroundWorker

    VB version here.

    This demo provides a dialogue that you can display modally over another form while that form does some background work. You basically write a normal DoWork event handler for a BackgroundWorker, as well as optional ProgresssChanged and RunWorkerCompleted event handlers, and pass them to the dialogue for it to use as handlers for the events of its own BackgroundWorker. That means that your form creates and displays the dialogue, the dialogue then kicks off a BackgroundWorker and it invokes methods in your form to do the work. That way, this same dialogue can be used for any work you like without change.

    The dialogue displays a Marquee ProgressBar by default and no Cancel button. If you provide a handler for the ProgressChanged event, it will display a Continuous ProgressBar so the actual progress can be displayed. Note that the Maximum of that ProgressBar is 100 so you must provide a genuine percentage when you call ReportProgress. If you set SupportsCancellation to True, the dialogue will also display a Cancel button. As always, it's up to you to process the cancellation request in your DoWork event handler.

    This attached solution was created in VS 2019 and targets .NET Framework 4.8. It contains both C# and VB version of the demo. If you're using an earlier version, you should still just be able to add the forms as existing items to a project of your own, as long as you're not using too-old a version.
    Attached Files Attached Files

  2. #2

    Thread Starter
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    105,579

    Re: Modal Wait Dialogue with BackgroundWorker

    For those who would like to see the code without having to download the solution, here you go:
    csharp Code:
    1. using System.ComponentModel;
    2. using System.Drawing;
    3. using System.Windows.Forms;
    4.  
    5. namespace Wunnell.Demo.BackgroundWorkerForm.CS
    6. {
    7.     public partial class BackgroundWorkerForm : Form
    8.     {
    9. #region Fields
    10.  
    11.         private readonly DoWorkEventHandler onDoWork;
    12.         private readonly ProgressChangedEventHandler onProgressChanged;
    13.         private readonly RunWorkerCompletedEventHandler onRunWorkerCompleted;
    14.  
    15. #endregion Fields
    16.  
    17. #region Constructors
    18.  
    19.         /// <summary>
    20.         /// Creates a new instance of the <see cref="BackgroundWorkerForm"/> class.
    21.         /// </summary>
    22.         /// <remarks>
    23.         /// Parameterless constructor is private to ensure handlers are provided for <see cref="BackgroundWorker"/>.
    24.         /// </remarks>
    25.         public BackgroundWorkerForm()
    26.         {
    27.             InitializeComponent();
    28.         }
    29.  
    30.         /// <summary>
    31.         /// Creates a new instance of the <see cref="BackgroundWorkerForm" /> class.
    32.         /// </summary>
    33.         /// <param name="onDoWork">
    34.         /// Handler for the <see cref="BackgroundWorker.DoWork">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    35.         /// </param>
    36.         public BackgroundWorkerForm(DoWorkEventHandler onDoWork)
    37.             : this()
    38.         {
    39.             this.onDoWork = onDoWork;
    40.  
    41.             // AddHandler is used for local event handlers so that remote event handlers can be registered first and thus executed first.
    42.  
    43.             // Remote event handlers
    44.             backgroundWorker1.DoWork += onDoWork;
    45.  
    46.             // Local event handlers
    47.             backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
    48.         }
    49.  
    50.         /// <summary>
    51.         /// Creates a new instance of the <see cref="BackgroundWorkerForm" /> class.
    52.         /// </summary>
    53.         /// <param name="onDoWork">
    54.         /// Handler for the <see cref="BackgroundWorker.DoWork">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    55.         /// </param>
    56.         /// <param name="onProgressChanged">
    57.         /// Handler for the <see cref="BackgroundWorker.ProgressChanged">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    58.         /// </param>
    59.         public BackgroundWorkerForm(DoWorkEventHandler onDoWork, ProgressChangedEventHandler onProgressChanged)
    60.             : this()
    61.         {
    62.             this.onDoWork = onDoWork;
    63.             this.onProgressChanged = onProgressChanged;
    64.  
    65.             // AddHandler is used for local event handlers so that remote event handlers can be registered first and thus executed first.
    66.  
    67.             // Remote event handlers
    68.             backgroundWorker1.DoWork += onDoWork;
    69.             backgroundWorker1.ProgressChanged += onProgressChanged;
    70.  
    71.             // Local event handlers
    72.             backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
    73.             backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
    74.  
    75.             // A ProgressChanged handler has been provided so the ProgressBar will be updated explicitly based on the BackgroundWorker.
    76.             backgroundWorker1.WorkerReportsProgress = true;
    77.             progressBar1.Style = ProgressBarStyle.Continuous;
    78.         }
    79.  
    80.         /// <summary>
    81.         /// Creates a new instance of the <see cref="BackgroundWorkerForm" /> class.
    82.         /// </summary>
    83.         /// <param name="onDoWork">
    84.         /// Handler for the <see cref="BackgroundWorker.DoWork">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    85.         /// </param>
    86.         /// <param name="onRunWorkerCompleted">
    87.         /// Handler for the <see cref="BackgroundWorker.RunWorkerCompleted">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    88.         /// </param>
    89.         public BackgroundWorkerForm(DoWorkEventHandler onDoWork, RunWorkerCompletedEventHandler onRunWorkerCompleted)
    90.             : this()
    91.         {
    92.             this.onDoWork = onDoWork;
    93.             this.onRunWorkerCompleted = onRunWorkerCompleted;
    94.  
    95.             // AddHandler is used for local event handlers so that remote event handlers can be registered first and thus executed first.
    96.  
    97.             // Remote event handlers
    98.             backgroundWorker1.DoWork += onDoWork;
    99.             backgroundWorker1.RunWorkerCompleted += onRunWorkerCompleted;
    100.  
    101.             // Local event handlers
    102.             backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
    103.         }
    104.  
    105.         /// <summary>
    106.         /// Creates a new instance of the <see cref="BackgroundWorkerForm" /> class.
    107.         /// </summary>
    108.         /// <param name="onDoWork">
    109.         /// Handler for the <see cref="BackgroundWorker.DoWork">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    110.         /// </param>
    111.         /// <param name="onProgressChanged">
    112.         /// Handler for the <see cref="BackgroundWorker.ProgressChanged">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    113.         /// </param>
    114.         /// <param name="onRunWorkerCompleted">
    115.         /// Handler for the <see cref="BackgroundWorker.RunWorkerCompleted">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    116.         /// </param>
    117.         public BackgroundWorkerForm(
    118.             DoWorkEventHandler onDoWork,
    119.             ProgressChangedEventHandler onProgressChanged,
    120.             RunWorkerCompletedEventHandler onRunWorkerCompleted)
    121.             : this()
    122.         {
    123.             this.onDoWork = onDoWork;
    124.             this.onProgressChanged = onProgressChanged;
    125.             this.onRunWorkerCompleted = onRunWorkerCompleted;
    126.  
    127.             // AddHandler is used for local event handlers so that remote event handlers can be registered first and thus executed first.
    128.  
    129.             // Remote event handlers
    130.             backgroundWorker1.DoWork += onDoWork;
    131.             backgroundWorker1.ProgressChanged += onProgressChanged;
    132.             backgroundWorker1.RunWorkerCompleted += onRunWorkerCompleted;
    133.  
    134.             // Local event handlers
    135.             backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
    136.             backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
    137.  
    138.             // A ProgressChanged handler has been provided so the ProgressBar will be updated explicitly based on the BackgroundWorker.
    139.             backgroundWorker1.WorkerReportsProgress = true;
    140.             progressBar1.Style = ProgressBarStyle.Continuous;
    141.         }
    142.  
    143. #endregion Constructors
    144.  
    145. #region Properties
    146.  
    147.         public bool SupportsCancellation
    148.         {
    149.             set
    150.             {
    151.                 backgroundWorker1.WorkerSupportsCancellation = value;
    152.  
    153.                 // If the worker can be cancelled, show the Cancel button and make the form big enough to see it.
    154.                 cancelWorkButton.Visible = value;
    155.                 ClientSize = new Size(284,
    156.                                       value ? 76 : 47);
    157.             }
    158.         }
    159.  
    160. #endregion Properties
    161.  
    162. #region Methods
    163.  
    164.         private void BackgroundWorkerForm_Shown(object sender, System.EventArgs e)
    165.         {
    166.             // Start the background work when the form is displayed.
    167.             backgroundWorker1.RunWorkerAsync();
    168.         }
    169.  
    170.         private void cancelWorkButton_Click(object sender, System.EventArgs e)
    171.         {
    172.             // Disable the button to prevent another click.
    173.             cancelWorkButton.Enabled = false;
    174.  
    175.             // Cancel the background work.
    176.             backgroundWorker1.CancelAsync();
    177.         }
    178.  
    179.         private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    180.         {
    181.             // Update the ProgressBar.
    182.             progressBar1.Value = e.ProgressPercentage;
    183.         }
    184.  
    185.         private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    186.         {
    187.             // Close the form when the work is done.
    188.             Close();
    189.         }
    190.  
    191.         private void BackgroundWorkerForm_FormClosing(object sender, FormClosingEventArgs e)
    192.         {
    193.             // Remote event handlers.
    194.  
    195.             if (onDoWork != null)
    196.             {
    197.                 backgroundWorker1.DoWork -= onDoWork;
    198.             }
    199.  
    200.             if (onProgressChanged != null)
    201.             {
    202.                 backgroundWorker1.ProgressChanged -= onProgressChanged;
    203.             }
    204.  
    205.             if (onRunWorkerCompleted != null)
    206.             {
    207.                 backgroundWorker1.RunWorkerCompleted -= onRunWorkerCompleted;
    208.             }
    209.  
    210.             // Local event handlers
    211.             backgroundWorker1.ProgressChanged -= backgroundWorker1_ProgressChanged;
    212.             backgroundWorker1.RunWorkerCompleted -= backgroundWorker1_RunWorkerCompleted;
    213.         }
    214.  
    215. #endregion Methods
    216.     }
    217. }
    csharp Code:
    1. using System.ComponentModel;
    2. using System.Threading;
    3. using System.Windows.Forms;
    4.  
    5. namespace Wunnell.Demo.BackgroundWorkerForm.CS
    6. {
    7.     public partial class Form1 : Form
    8.     {
    9.         public Form1()
    10.         {
    11.             InitializeComponent();
    12.         }
    13.  
    14.         // This method will be executed by the BackgroundWorker in the dialogue.
    15.         private void BackgroundWorkerForm_DoWork(object sender, DoWorkEventArgs e)
    16.         {
    17.             var worker = (BackgroundWorker)sender;
    18.  
    19.             for (var i = 0; i <= 100; i++)
    20.             {
    21.                 if (worker.CancellationPending)
    22.                 {
    23.                     e.Cancel = true;
    24.  
    25.                     break;
    26.                 }
    27.  
    28.                 if (reportProgressCheckBox.Checked)
    29.                 {
    30.                     worker.ReportProgress(i);
    31.                 }
    32.  
    33.                 Thread.Sleep(100);
    34.             }
    35.         }
    36.  
    37.         // This method will be executed by the BackgroundWorker in the dialogue.
    38.         private void BackgroundWorkerForm_ProgressChanged(object sender, ProgressChangedEventArgs e)
    39.         {
    40.             statusLabel.Text = (e.ProgressPercentage / 100.0).ToString("p0");
    41.         }
    42.  
    43.         // This method will be executed by the BackgroundWorker in the dialogue.
    44.         private void BackgroundWorkerForm_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    45.         {
    46.             statusLabel.Text = e.Cancelled
    47.                                    ? "Operation cancelled"
    48.                                    : "Operation complete";
    49.         }
    50.  
    51.         private void runButton_Click(object sender, System.EventArgs e)
    52.         {
    53.             // Display the dialogue to initiate the background work.
    54.             using (var waitDialogue = GetWaitDialogue())
    55.             {
    56.                 waitDialogue.ShowDialog();
    57.             }
    58.         }
    59.  
    60.         private BackgroundWorkerForm GetWaitDialogue()
    61.         {
    62.             var dialogue = new BackgroundWorkerForm();
    63.  
    64.             // Only provide a ProgressChanged handler if the corresponding CheckBox is checked.
    65.             if (reportProgressCheckBox.Checked)
    66.             {
    67.                 dialogue = new BackgroundWorkerForm(BackgroundWorkerForm_DoWork,
    68.                                                     BackgroundWorkerForm_ProgressChanged,
    69.                                                     BackgroundWorkerForm_RunWorkerCompleted);
    70.             }
    71.             else
    72.             {
    73.                 dialogue = new BackgroundWorkerForm(BackgroundWorkerForm_DoWork,
    74.                                                     BackgroundWorkerForm_RunWorkerCompleted);
    75.             }
    76.  
    77.             // Only display a Cancel button if the corresponding CheckBox is checked.
    78.             dialogue.SupportsCancellation = allowCancellationCheckBox.Checked;
    79.  
    80.             return dialogue;
    81.         }
    82.     }
    83. }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width