Click here to Skip to main content
15,888,461 members
Please Sign up or sign in to vote.
1.44/5 (3 votes)
Hi,

I'm making a program that goes through this flow:

1) Do Task 1
2) Update progressbar to 33%
3) Do Task 2
4) Update progressbar to 67%
5) Do Task 3
6) Update progressbar to 100%
7) Msgbox("Done")

I've omitted the tasks because they're unrelated to this question.

The problem is that the progressbar only updates if a msgbox is shown in the Tick1() event, taking focus away from the form.

I have 3 BackgroundWorkers: Part1, Part2 and Part3.
I also have 3 timers: Increment1Timer, Increment2Timer and Increment3Timer.

This is my code:
VB
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            Part1.RunWorkerAsync()
    End Sub
   
    Private Sub Part1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles Part1.DoWork
        PictureBox1.Image = My.Resources.shield
        Label1.Text = "Performing task 1..."
        Try
       (Do Task 1)
            Threading.Thread.Sleep(2000)
            Increment1Timer.Start()
             Catch ex As Exception
            Threading.Thread.Sleep(2000)
            PictureBox1.Image = My.Resources.cross
            Label1.Text = "Error-UAC required"
            Threading.Thread.Sleep(2000)
            Dim proc As New ProcessStartInfo
            proc.UseShellExecute = True
            proc.WorkingDirectory = Environment.CurrentDirectory
            proc.FileName = Application.ExecutablePath
            proc.Verb = "runas"
            Try
                Process.Start(proc)
            Catch ex2 As Exception
            End Try
            Application.Exit()
        End Try
    End Sub
    Private Delegate Sub DoUIWorkHandler()
    Private Sub Increment1Timer_Tick(sender As System.Object, e As System.EventArgs) Handles Increment1Timer.Tick
        If (NeroBar1.InvokeRequired) Then
            NeroBar1.Invoke(New DoUIWorkHandler(AddressOf Tick1))
        Else
            Tick1()
        End If
    End Sub
    Private Sub Tick1()
        If NeroBar1.Value = 33 Then
            Increment1Timer.Stop()
            Part2.RunWorkerAsync()
        Else
            NeroBar1.Value += 1
        End If
    End Sub
    Private Sub Part2_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles Part2.DoWork
        PictureBox1.Image = My.Resources.task
        Label1.Text = "Performing task 2..."
              (Do Task 2)
              Threading.Thread.Sleep(2000)
        Part2.ReportProgress(67)
        Increment2Timer.Start()
    End Sub
    Private Sub Increment2Timer_Tick(sender As System.Object, e As System.EventArgs) Handles Increment2Timer.Tick
        If (NeroBar1.InvokeRequired) Then
            NeroBar1.Invoke(New DoUIWorkHandler(AddressOf Tick2))
        Else
            Tick2()
        End If
    End Sub
    Private Sub Tick2()
        If NeroBar1.Value = 67 Then
            Increment2Timer.Stop()
            Part3.RunWorkerAsync()
        Else
            NeroBar1.Value += 1
        End If
    End Sub
    Private Sub Part3_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles Part3.DoWork
        PictureBox1.Image = My.Resources.task
        Label1.Text = "Performing task 3..."
        Part3.ReportProgress(100)
        Increment3Timer.Start()
    End Sub
    Private Sub Increment3Timer_Tick(sender As System.Object, e As System.EventArgs) Handles Increment3Timer.Tick
        If NeroBar1.Value = 100 Then
            If (NeroBar1.InvokeRequired) Then
                NeroBar1.Invoke(New DoUIWorkHandler(AddressOf Tick3))
            Else
                Tick3()
            End If
                   MsgBox("Done")
        Else
            NeroBar1.Value += 1
        End If
    End Sub
    Private Sub Tick3()
        If NeroBar1.Value = 100 Then
            Increment1Timer.Stop()
        Else
            NeroBar1.Value += 1
        End If
    End Sub


Please help!
Posted
Comments
Sergey Alexandrovich Kryukov 5-Jun-14 12:55pm    
There is no such concept as "call a timer". Tick1() is not an event. And so on... Why calling BackgroundWorker.RunWorkerAsync from a timer event handler? The code design is screwed up and over-compicated quite well. I don't think we have something to discuss here, unless you explain what did you want to achieve in first place.
—SA
[no name] 7-Jun-14 7:17am    
As mentioned, the purpose is unnecessary to this question.
Sergey Alexandrovich Kryukov 7-Jun-14 22:39pm    
Well, this is what you think. In this case, you are on your own... :-)
Good luck,
—SA
[no name] 5-Jun-14 14:51pm    
"Strange problems" occur when you try and access UI controls from background threads.
[no name] 7-Jun-14 7:17am    
That's nice. Now are you here to help or to insult?

1 solution

Not sure if the OP is still in need of a solution judging from what replies he got - nothing of value - and the date this question was posted.

I have a similar situation while sending an email with attachments. I use a single Timer control to manage the "firing" order of my Backgroundworker with the 2 conditions that must be met before the next Backgroundworker will fire, these are (1) a Label control to confirm that the previous action has successfully completed and (2) that the previous Backgroundworker has ended - you don't want two backgroundworkers to run at the same time, especially when the one is dependent on the work done by the other.

When sending an email with attachments (images from a DB) this is how my workflow for:
(1) Retrieve images (binary format) from DB into memory stream. Save the memorystream to a file on the local disk.
(2) Prepare and send email with attachments.
(3) Remove images from file system.

During the process I update a Label and a Progressbar.

This is the logic behind using 3 Backgroundworkers with a single Timer control:

VB
'***********************************************************************************
 '* IMPORTANT !!!!!                                                                 *
 '*-----------------                                                                *
 '* We will be using 3 BackgroundWorkers to accomplish sending an Email message.    *
 '* 1. Export Images  (bkwExportImg)                                                *
 '* 2. Send Messsage  (bkwSendMsg)                                                  *
 '* 3. Delete Images  (bkwDeleteImg)                                                *
 '* !!! BackgroundWorkers are fired up in the above order by means of a Timer!!!    *
 '* Threads are used to update the Main form UI                                     *
 '***********************************************************************************
 'TIMER - Timer is used to fire the Send Message Backgroundworkers sequentially
 Private Sub tmrBackgroundworker_Tick(sender As System.Object, e As System.EventArgs) Handles tmrBackgroundworker.Tick
     If bgwExportImage.IsBusy = False AndAlso Me.tsSendMailStatus.Text = "Preparing Email message" Then
         'Start the Export process
         bgwExportImage.RunWorkerAsync()
     ElseIf bgwSendMessage.IsBusy = False AndAlso Me.tsSendMailStatus.Text = "Export completed" Then
         'Send the message
         bgwSendMessage.RunWorkerAsync()
     ElseIf bgwDeleteImages.IsBusy = False AndAlso Me.tsSendMailStatus.Text = "Message sent" Then
         'Delete Image files
         bgwDeleteImages.RunWorkerAsync()
     End If
 End Sub


I hope this helps you out a little. It works really well for me and has been working perfectly for some time now and I haven't has a single instance where it failed on me.

Something to keep in mind is to first test if any backgroundworkers are running before you attempt to fire your first backgroundworker.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900