PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197

PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197
Modal Wait Dialogue with BackgroundWorker-VBForums
Results 1 to 4 of 4

Thread: Modal Wait Dialogue with BackgroundWorker

  1. #1

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

    Modal Wait Dialogue with BackgroundWorker

    This is something that I've been meaning to do for some time but never got around to previously. Earlier today - and not for the first time - I saw someone trying to display a modal wait dialogue while they did some work and going about it in very much the wrong way.

    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.

    Note that this project was created in VS 2017 and targets .NET 4.7.2. 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
    Last edited by jmcilhinney; Jan 24th, 2019 at 05:52 PM. Reason: Removed erroneous Handles clause and updated attachment.

  2. #2

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

    Re: Modal Wait Dialogue with BackgroundWorker

    For those who would like to see the code without having to download the solution, here you go:
    vb.net Code:
    1. Imports System.ComponentModel
    2.  
    3. Public Class BackgroundWorkerForm
    4.  
    5. #Region "Constructors"
    6.  
    7.     ''' <summary>
    8.     ''' Creates a new instance of the <see cref="BackgroundWorkerForm"/> class.
    9.     ''' </summary>
    10.     ''' <remarks>
    11.     ''' Parameterless constructor is private to ensure handlers are provided for <see cref="BackgroundWorker"/>.
    12.     ''' </remarks>
    13.     Private Sub New()
    14.         ' This call is required by the designer.
    15.         InitializeComponent()
    16.     End Sub
    17.  
    18.     ''' <summary>
    19.     ''' Creates a new instance of the <see cref="BackgroundWorkerForm" /> class.
    20.     ''' </summary>
    21.     ''' <param name="onDoWork">
    22.     ''' Handler for the <see cref="BackgroundWorker.DoWork">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    23.     ''' </param>
    24.     Public Sub New(onDoWork As DoWorkEventHandler)
    25.         Me.New()
    26.  
    27.         'Remote event handlers
    28.         AddHandler BackgroundWorker1.DoWork, onDoWork
    29.  
    30.         'Local event handlers
    31.         AddHandler BackgroundWorker1.RunWorkerCompleted, AddressOf BackgroundWorker1_RunWorkerCompleted
    32.     End Sub
    33.  
    34.     ''' <summary>
    35.     ''' Creates a new instance of the <see cref="BackgroundWorkerForm" /> class.
    36.     ''' </summary>
    37.     ''' <param name="onDoWork">
    38.     ''' Handler for the <see cref="BackgroundWorker.DoWork">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    39.     ''' </param>
    40.     ''' <param name="onProgressChanged">
    41.     ''' Handler for the <see cref="BackgroundWorker.ProgressChanged">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    42.     ''' </param>
    43.     Public Sub New(onDoWork As DoWorkEventHandler,
    44.                    onProgressChanged As ProgressChangedEventHandler)
    45.         Me.New()
    46.  
    47.         'Remote event handlers
    48.         AddHandler BackgroundWorker1.DoWork, onDoWork
    49.         AddHandler BackgroundWorker1.ProgressChanged, onProgressChanged
    50.  
    51.         'Local event handlers
    52.         AddHandler BackgroundWorker1.ProgressChanged, AddressOf BackgroundWorker1_ProgressChanged
    53.         AddHandler BackgroundWorker1.RunWorkerCompleted, AddressOf BackgroundWorker1_RunWorkerCompleted
    54.  
    55.         'A ProgressChanged handler has been provided so the ProgressBar will be updated explicitly based on the BackgroundWorker.
    56.         BackgroundWorker1.WorkerReportsProgress = True
    57.         ProgressBar1.Style = ProgressBarStyle.Continuous
    58.     End Sub
    59.  
    60.     ''' <summary>
    61.     ''' Creates a new instance of the <see cref="BackgroundWorkerForm" /> class.
    62.     ''' </summary>
    63.     ''' <param name="onDoWork">
    64.     ''' Handler for the <see cref="BackgroundWorker.DoWork">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    65.     ''' </param>
    66.     ''' <param name="onRunWorkerCompleted">
    67.     ''' Handler for the <see cref="BackgroundWorker.RunWorkerCompleted">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    68.     ''' </param>
    69.     Public Sub New(onDoWork As DoWorkEventHandler,
    70.                    onRunWorkerCompleted As RunWorkerCompletedEventHandler)
    71.         Me.New()
    72.  
    73.         'Remote event handlers
    74.         AddHandler BackgroundWorker1.DoWork, onDoWork
    75.         AddHandler BackgroundWorker1.RunWorkerCompleted, onRunWorkerCompleted
    76.  
    77.         'Local event handlers
    78.         AddHandler BackgroundWorker1.RunWorkerCompleted, AddressOf BackgroundWorker1_RunWorkerCompleted
    79.     End Sub
    80.  
    81.     ''' <summary>
    82.     ''' Creates a new instance of the <see cref="BackgroundWorkerForm" /> class.
    83.     ''' </summary>
    84.     ''' <param name="onDoWork">
    85.     ''' Handler for the <see cref="BackgroundWorker.DoWork">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    86.     ''' </param>
    87.     ''' <param name="onProgressChanged">
    88.     ''' Handler for the <see cref="BackgroundWorker.ProgressChanged">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    89.     ''' </param>
    90.     ''' <param name="onRunWorkerCompleted">
    91.     ''' Handler for the <see cref="BackgroundWorker.RunWorkerCompleted">RunWorkerCompleted</see> event of a <see cref="BackgroundWorker"/>.
    92.     ''' </param>
    93.     Public Sub New(onDoWork As DoWorkEventHandler,
    94.                    onProgressChanged As ProgressChangedEventHandler,
    95.                    onRunWorkerCompleted As RunWorkerCompletedEventHandler)
    96.         Me.New()
    97.  
    98.         'Remote event handlers
    99.         AddHandler BackgroundWorker1.DoWork, onDoWork
    100.         AddHandler BackgroundWorker1.ProgressChanged, onProgressChanged
    101.         AddHandler BackgroundWorker1.RunWorkerCompleted, onRunWorkerCompleted
    102.  
    103.         'Local event handlers
    104.         AddHandler BackgroundWorker1.ProgressChanged, AddressOf BackgroundWorker1_ProgressChanged
    105.         AddHandler BackgroundWorker1.RunWorkerCompleted, AddressOf BackgroundWorker1_RunWorkerCompleted
    106.  
    107.         'A ProgressChanged handler has been provided so the ProgressBar will be updated explicitly based on the BackgroundWorker.
    108.         BackgroundWorker1.WorkerReportsProgress = True
    109.         ProgressBar1.Style = ProgressBarStyle.Continuous
    110.     End Sub
    111.  
    112. #End Region 'Constructors
    113.  
    114. #Region "Properties"
    115.  
    116.     Public WriteOnly Property SupportsCancellation As Boolean
    117.         Set
    118.             BackgroundWorker1.WorkerSupportsCancellation = Value
    119.  
    120.             'If the worker can be cancelled, show the Cancel button and make the form big enough to see it.
    121.             cancelWorkButton.Visible = Value
    122.             Height = If(Value, 115, 86)
    123.         End Set
    124.     End Property
    125.  
    126. #End Region 'Properties
    127.  
    128.     Private Sub BackgroundWorkerForm_Shown(sender As Object, e As EventArgs) Handles Me.Shown
    129.         'Start the background work when the form is displayed.
    130.         BackgroundWorker1.RunWorkerAsync()
    131.     End Sub
    132.  
    133.     Private Sub cancelWorkButton_Click(sender As Object, e As EventArgs) Handles cancelWorkButton.Click
    134.         'Disable the button to prevent another click.
    135.         cancelWorkButton.Enabled = False
    136.  
    137.         'Cancel the background work.
    138.         BackgroundWorker1.CancelAsync()
    139.     End Sub
    140.  
    141.     Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)
    142.         'Update the ProgressBar.
    143.         ProgressBar1.Value = e.ProgressPercentage
    144.     End Sub
    145.  
    146.     Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs)
    147.         'Close the form when the work is done.
    148.         Close()
    149.     End Sub
    150.  
    151. End Class
    Here's the code for the demo main form:
    vb.net Code:
    1. Imports System.ComponentModel
    2. Imports System.Threading
    3.  
    4. Public Class Form1
    5.  
    6.     Private Sub BackgroundWorkerForm_DoWork(sender As Object, e As DoWorkEventArgs)
    7.         'Simulate some time-consuming work.
    8.         For i = 0 To 100
    9.             Dim worker = DirectCast(sender, BackgroundWorker)
    10.  
    11.             If worker.CancellationPending Then
    12.                 e.Cancel = True
    13.  
    14.                 Exit For
    15.             End If
    16.  
    17.             If reportProgressCheckBox.Checked Then
    18.                 worker.ReportProgress(i)
    19.             End If
    20.  
    21.             Thread.Sleep(100)
    22.         Next
    23.     End Sub
    24.  
    25.     'This method will be executed by the BackgroundWorker in the dialogue.
    26.     Private Sub BackgroundWorkerForm_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)
    27.         statusLabel.Text = (e.ProgressPercentage / 100).ToString("p0")
    28.     End Sub
    29.  
    30.     'This method will be executed by the BackgroundWorker in the dialogue.
    31.     Private Sub BackgroundWorkerForm_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs)
    32.         statusLabel.Text = If(e.Cancelled, "Operation cancelled", "Operation complete")
    33.     End Sub
    34.  
    35.     Private Sub runButton_Click(sender As Object, e As EventArgs) Handles runButton.Click
    36.         'Display the dialogue to initiate the background work.
    37.         Using waitDialogue = GetWaitDialogue()
    38.             waitDialogue.ShowDialog()
    39.         End Using
    40.     End Sub
    41.  
    42.     Private Function GetWaitDialogue() As BackgroundWorkerForm
    43.         Dim dialogue As BackgroundWorkerForm
    44.  
    45.         'Only provide a ProgressChanged handler if the corresponding CheckBox is checked.
    46.         If reportProgressCheckBox.Checked Then
    47.             dialogue = New BackgroundWorkerForm(AddressOf BackgroundWorkerForm_DoWork,
    48.                                                 AddressOf BackgroundWorkerForm_ProgressChanged,
    49.                                                 AddressOf BackgroundWorkerForm_RunWorkerCompleted)
    50.         Else
    51.             dialogue = New BackgroundWorkerForm(AddressOf BackgroundWorkerForm_DoWork,
    52.                                                 AddressOf BackgroundWorkerForm_RunWorkerCompleted)
    53.         End If
    54.  
    55.         'Only display a Cancel button if the corresponding CheckBox is checked.
    56.         dialogue.SupportsCancellation = allowCancellationCheckBox.Checked
    57.  
    58.         Return dialogue
    59.     End Function
    60. End Class
    Last edited by jmcilhinney; Jan 24th, 2019 at 05:38 PM. Reason: Removed erroneous Handles clause.

  3. #3

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

    Re: Modal Wait Dialogue with BackgroundWorker

    Actually, there's one small mistake in the original code I posted. The BackgroundWorker1_ProgressChanged method should not have a Handles clause on it. It won't stop things working but it means that that method will be executed twice when progress is enable.

  4. #4
    PowerPoster
    Join Date
    Feb 2016
    Location
    Tennessee
    Posts
    2,259

    Re: Modal Wait Dialogue with BackgroundWorker

    Great code! Thanks a bunch...

Posting Permissions

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



Featured


Click Here to Expand Forum to Full Width