Results 1 to 23 of 23

Thread: BackgroundWorker problem

  1. #1

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    BackgroundWorker problem

    Odd question and hopefully easy answer
    I am trying to loop through a collection and download a set of files but because
    each download is using the same backgroundworker I am running into a problem with collisions and
    other stuff


    When I click the button I get this error

    An unhandled exception of type 'System.InvalidOperationException' occurred in System.dll

    Additional information: This BackgroundWorker is currently busy and cannot run multiple tasks concurrently.


    If only one file is missing it seems to download it ok. But if more than one file is missing it errors.

    I need help figuring out how to delay the next download until the one before it is done and still update the progress bar.

    I'm guessing [with my SO limited knowledge of VB] that because I am running a backgroundworker and it's set to async that I
    somekind of way to run the worker then end it before starting the next. But how is totally eluding me.


    I have a form called DLForm
    5 Labels
    1 RichTextBox
    1 ProgressBar
    1 Button
    1 BackgroundWorker
    1 Timer

    Code:
    Imports System.Net
    Imports System.IO
    'Imports Ionic.Zip
    Imports System.Runtime.InteropServices
    Public Class DLForm
    #Region " Functions and Constants "
        <DllImport("user32.dll")> _
        Public Shared Function ReleaseCapture() As Boolean
        End Function
        <DllImport("user32.dll")> _
        Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        End Function
        Public Const WM_NCLBUTTONDOWN As Integer = &HA1
        Public Const HTBORDER As Integer = 18
        Public Const HTBOTTOM As Integer = 15
        Public Const HTBOTTOMLEFT As Integer = 16
        Public Const HTBOTTOMRIGHT As Integer = 17
        Public Const HTCAPTION As Integer = 2
        Public Const HTLEFT As Integer = 10
        Public Const HTRIGHT As Integer = 11
        Public Const HTTOP As Integer = 12
        Public Const HTTOPLEFT As Integer = 13
        Public Const HTTOPRIGHT As Integer = 14
    #End Region
    #Region " Moving & Resizing methods "
        Public Sub MoveForm()
            ReleaseCapture()
            SendMessage(Me.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0)
        End Sub
    #End Region
        Private Sub SavePosition(ByVal frm As Form, ByVal app_name As String)
            SaveSetting(app_name, "Geometry", "WindowState", frm.WindowState)
            If frm.WindowState = FormWindowState.Normal Then
                SaveSetting(app_name, "Geometry", "Left", frm.Left)
                SaveSetting(app_name, "Geometry", "Top", frm.Top)
                SaveSetting(app_name, "Geometry", "Width", frm.Width)
                SaveSetting(app_name, "Geometry", "Height", frm.Height)
            Else
                SaveSetting(app_name, "Geometry", "Left", frm.RestoreBounds.Left)
                SaveSetting(app_name, "Geometry", "Top", frm.RestoreBounds.Top)
                SaveSetting(app_name, "Geometry", "Width", frm.RestoreBounds.Width)
                SaveSetting(app_name, "Geometry", "Height", frm.RestoreBounds.Height)
            End If
        End Sub
        Private Sub RestorePosition(ByVal frm As Form, ByVal app_name As String)
            frm.SetBounds( _
                GetSetting(app_name, "Geometry", "Left", Me.RestoreBounds.Left), _
                GetSetting(app_name, "Geometry", "Top", Me.RestoreBounds.Top), _
                GetSetting(app_name, "Geometry", "Width", Me.RestoreBounds.Width), _
                GetSetting(app_name, "Geometry", "Height", Me.RestoreBounds.Height) _
            )
            Me.WindowState = GetSetting(app_name, "Geometry", "WindowState", Me.WindowState)
        End Sub
        Public link As String
        Public Filename As String
        Public FilenameGP As String
        Public FilenameIDE As String
        Public FilenameMHV As String
        Private Sub DLForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            RestorePosition(Me, "DL4")
            Label5.Visible = False
        End Sub
        Private Sub DLForm_Closing(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
            SavePosition(Me, "DL4")
        End Sub
        Private Sub Downloader_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker.DoWork
            'mod this
            Filename = Label5.Text
            File.Delete("C:\Windows\Temp\MPNGTemp\" & Filename)
            If Filename = "GitPortable.zip" Then
                link = "http://www.sshcs.com/MPNG/ArduPilot-Arduino-1.0.3-windows.zip"
            End If
            If Filename = "ArduPilot-Arduino-1.0.3-windows.zip" Then
                link = "http://www.sshcs.com/MPNG/GitPortable.zip"
            End If
            If Filename = "MHV_AVR_Tools_20121007.exe" Then
                link = "http://firmware.diydrones.com/Tools/Arduino/MHV_AVR_Tools_20121007.exe"
            End If
            Try
                Dim size As Integer
                Dim wr As WebRequest
                wr = WebRequest.Create(link)
                Dim webr As WebResponse = wr.GetResponse
                size = webr.ContentLength
                size = size / 1024
                ProgressBar1.Maximum = size
                Label2.Text = size
                Dim wc As New WebClient
                wc.DownloadFile(link, "C:\Windows\Temp\MPNGTemp\" & Filename)
                RichTextBox1.AppendText("Finished downloading " & Filename & vbCrLf)
            Catch ex As Exception
            End Try
            Exit Sub
        End Sub
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            Filename = Label5.Text
            Dim amount As Integer
            Try
                If System.IO.File.Exists("C:\Windows\Temp\MPNGTemp\" & Filename) Then
                    Dim o As New System.IO.FileInfo("C:\Windows\Temp\MPNGTemp\" & Filename)
                    amount = o.Length
                    amount = amount / 1024
                    Label3.Text = amount
                    ProgressBar1.Value = amount
                End If
            Catch ex As Exception
            End Try
        End Sub
        Private Sub Downloader_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker.RunWorkerCompleted
            RichTextBox1.AppendText("Finished Downloading" & vbCrLf)
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim colFiles As New Collection
            Dim intCtr As Integer
            colFiles.Add("GitPortable.zip")
            colFiles.Add("ArduPilot-Arduino-1.0.3-windows.zip")
            colFiles.Add("MHV_AVR_Tools_20121007.exe")
    
            For intCtr = 1 To colFiles.Count
    				Label5.Text = colFiles(intCtr)
                If System.IO.File.Exists("C:\Windows\Temp\MPNGTemp\" & colFiles(intCtr)) Then
                    'already there so skip download
                    RichTextBox1.AppendText(colFiles(intCtr) & " Already exists so skipping" & vbCrLf)
                Else
                    Label5.Text = colFiles(intCtr)
                    RichTextBox1.AppendText(colFiles(intCtr) & " does not exist so downloading" & vbCrLf)
                    Control.CheckForIllegalCrossThreadCalls = False
                    Timer1.Start()
                    BackgroundWorker.RunWorkerAsync()
                End If
            Next intCtr
        End Sub
    End Class

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: BackgroundWorker problem

    For future reference, please only post RELEVANT code because everything else just clouds the issue. You ask a question about downloading files using a BackgroundWorker and we have to wade through irrelevant stuff about resizing and persisting size information and unmanaged that we don't care about. If you make it harder for us to help then it's a waste of our time and makes it less likely that you'll get the help you want, so everybody loses.

    Anyway, a BackgroundWorker can only run once at a time. Either check the IsBusy property first to make sure that you don't try to run it more than once at a time or else find another way to implement your multi-threading so that you can perform multiple background tasks at the same time, e.g. Task or ThreadPool.

    Also, get rid of that line that sets CheckForIllegalCrossThreadCalls to False and NEVER do that again. That defeats the purpose of the BackgroundWorker in the first place. Follow the CodeBank link in my signature below and check out my thread on Using The BackgroundWorker to learn how to use it properly. DO NOT do anything related to the UI in the DoWork event handler. Anything that touches the UI gets done in the ProgressChanged or RunWorkerCompleted event handler. That's why the BackgroundWorker exists.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3
    Addicted Member
    Join Date
    Oct 2012
    Location
    Springfield, IL
    Posts
    142

    Re: BackgroundWorker problem

    VS 2012 has new features to make what you are trying to do as simple as apple pie

    Async and Await

    I just posted code that is fully asynchronous and downloads multiple files while looping through a regular expression match collection and updates the UI all without using a bacgroundworker or using mutli-threading.

    I think you could accomplish what you want to do by replacing the BacgroundWorker.RunWorkerAsync and calling the code below instead. .
    I haven't tested it but I only changed 2 things from your original code.

    vb.net Code:
    1. Private Async Sub NoMoreBlastedBackgroundWorker()
    2.         'mod this
    3.         FileName = Label5.Text
    4.         File.Delete("C:\Windows\Temp\MPNGTemp\" & FileName)
    5.         If FileName = "GitPortable.zip" Then
    6.             link = "http://www.sshcs.com/MPNG/ArduPilot-Arduino-1.0.3-windows.zip"
    7.         End If
    8.         If FileName = "ArduPilot-Arduino-1.0.3-windows.zip" Then
    9.             link = "http://www.sshcs.com/MPNG/GitPortable.zip"
    10.         End If
    11.         If FileName = "MHV_AVR_Tools_20121007.exe" Then
    12.             link = "http://firmware.diydrones.com/Tools/Arduino/MHV_AVR_Tools_20121007.exe"
    13.         End If
    14.         Try
    15.             Dim size As Integer
    16.             Dim wr As WebRequest
    17.             wr = WebRequest.Create(link)
    18.             ' Async response.
    19.             Dim webr As WebResponse = Await wr.GetResponseAsync
    20.             size = webr.ContentLength
    21.             size = size / 1024
    22.             ProgressBar1.Maximum = size
    23.             Label2.Text = size
    24.             Dim wc As New WebClient
    25.             'Async downloading file.  Simple as pie!
    26.             Await wc.DownloadFileTaskAsync(link, "C:\Windows\Temp\MPNGTemp\" & FileName)
    27.             RichTextBox1.AppendText("Finished downloading " & FileName & vbCrLf)
    28.         Catch ex As Exception
    29.         End Try
    30.  
    31.     End Sub

  4. #4

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    Quote Originally Posted by jmcilhinney View Post
    For future reference, please only post RELEVANT code because everything else just clouds the issue. You ask a question about downloading files using a BackgroundWorker and we have to wade through irrelevant stuff about resizing and persisting size information and unmanaged that we don't care about. If you make it harder for us to help then it's a waste of our time and makes it less likely that you'll get the help you want, so everybody loses.

    Anyway, a BackgroundWorker can only run once at a time. Either check the IsBusy property first to make sure that you don't try to run it more than once at a time or else find another way to implement your multi-threading so that you can perform multiple background tasks at the same time, e.g. Task or ThreadPool.

    Also, get rid of that line that sets CheckForIllegalCrossThreadCalls to False and NEVER do that again. That defeats the purpose of the BackgroundWorker in the first place. Follow the CodeBank link in my signature below and check out my thread on Using The BackgroundWorker to learn how to use it properly. DO NOT do anything related to the UI in the DoWork event handler. Anything that touches the UI gets done in the ProgressChanged or RunWorkerCompleted event handler. That's why the BackgroundWorker exists.
    Sorry

    The problem [for me at least] is I don't WANT it to run all 3 at once. I want it to run one, and when it's complete then run the next, and when that is completed run the final one.

    I will look into the IsBusy event and see if that will do what I need.

    thanks for taking the time to set me straight on a few key aspects of the question.

  5. #5

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    Quote Originally Posted by OICU812 View Post
    VS 2012 has new features to make what you are trying to do as simple as apple pie

    Async and Await

    I just posted code that is fully asynchronous and downloads multiple files while looping through a regular expression match collection and updates the UI all without using a bacgroundworker or using mutli-threading.

    I think you could accomplish what you want to do by replacing the BacgroundWorker.RunWorkerAsync and calling the code below instead. .
    I haven't tested it but I only changed 2 things from your original code.

    vb.net Code:
    1. Private Async Sub NoMoreBlastedBackgroundWorker()
    2.         'mod this
    3.         FileName = Label5.Text
    4.         File.Delete("C:\Windows\Temp\MPNGTemp\" & FileName)
    5.         If FileName = "GitPortable.zip" Then
    6.             link = "http://www.sshcs.com/MPNG/ArduPilot-Arduino-1.0.3-windows.zip"
    7.         End If
    8.         If FileName = "ArduPilot-Arduino-1.0.3-windows.zip" Then
    9.             link = "http://www.sshcs.com/MPNG/GitPortable.zip"
    10.         End If
    11.         If FileName = "MHV_AVR_Tools_20121007.exe" Then
    12.             link = "http://firmware.diydrones.com/Tools/Arduino/MHV_AVR_Tools_20121007.exe"
    13.         End If
    14.         Try
    15.             Dim size As Integer
    16.             Dim wr As WebRequest
    17.             wr = WebRequest.Create(link)
    18.             ' Async response.
    19.             Dim webr As WebResponse = Await wr.GetResponseAsync
    20.             size = webr.ContentLength
    21.             size = size / 1024
    22.             ProgressBar1.Maximum = size
    23.             Label2.Text = size
    24.             Dim wc As New WebClient
    25.             'Async downloading file.  Simple as pie!
    26.             Await wc.DownloadFileTaskAsync(link, "C:\Windows\Temp\MPNGTemp\" & FileName)
    27.             RichTextBox1.AppendText("Finished downloading " & FileName & vbCrLf)
    28.         Catch ex As Exception
    29.         End Try
    30.  
    31.     End Sub
    I'm guessing you are doing this against a different version of .NET

    I need to target this for 3.5 or lower, because as sucky as it is, quite a few peeps still run XP.

    When I added that I get a ton of errors I read your other post and if it wasn't for the need to support XP it looks EXACTLY like what I need

    sigh. Back to seeing if IsBusy can do what I need.

    Thanks for taking the time to respond.

  6. #6
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: BackgroundWorker problem

    Quote Originally Posted by thequestor View Post
    Sorry

    The problem [for me at least] is I don't WANT it to run all 3 at once. I want it to run one, and when it's complete then run the next, and when that is completed run the final one.

    I will look into the IsBusy event and see if that will do what I need.

    thanks for taking the time to set me straight on a few key aspects of the question.
    Are you saying that you want the first download done on the first click, the second on the second and the third on the third, or that you want all three done on the one click, one after the other?
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    Quote Originally Posted by jmcilhinney View Post
    Are you saying that you want the first download done on the first click, the second on the second and the third on the third, or that you want all three done on the one click, one after the other?
    all 3 one after the other on a single click. I don't have an issue with it if I do it one by one [ie a click for each].

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: BackgroundWorker problem

    Quote Originally Posted by thequestor View Post
    all 3 one after the other on a single click. I don't have an issue with it if I do it one by one [ie a click for each].
    Then write a method that downloads a file and call it three times from the DoWork event handler. It's that simple. Download one file, then download the second and then download the third.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  9. #9

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    Quote Originally Posted by jmcilhinney View Post
    Then write a method that downloads a file and call it three times from the DoWork event handler. It's that simple. Download one file, then download the second and then download the third.
    That's what I thought I already did which is the reason I came here asking.

  10. #10
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: BackgroundWorker problem

    Quote Originally Posted by thequestor View Post
    That's what I thought I already did which is the reason I came here asking.
    Look at this from your DoWork event handler:
    Code:
            If Filename = "GitPortable.zip" Then
                link = "http://www.sshcs.com/MPNG/ArduPilot-Arduino-1.0.3-windows.zip"
            End If
            If Filename = "ArduPilot-Arduino-1.0.3-windows.zip" Then
                link = "http://www.sshcs.com/MPNG/GitPortable.zip"
            End If
            If Filename = "MHV_AVR_Tools_20121007.exe" Then
                link = "http://firmware.diydrones.com/Tools/Arduino/MHV_AVR_Tools_20121007.exe"
            End If
    Filename can't be all three of those values can it? It can only have one value at a time so your code is only going to download one file at a time.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  11. #11

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    I "thought" I could just make a collection and just loop through them, like I do with arrays, one at a time, but because, I guess, they are running async it is running all 3 without waiting for the 1st loop to finish. I haven't found a way to do it synchronous.

    I pretty much was hoping it would be able to run the 1st loop and finish then run the 2nd loop and finish and finally the last loop.

    I mean I guess I could somehow chain them but I was trying out just using one bit of code to do all 3 things

  12. #12
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: BackgroundWorker problem

    You can use a loop. There is only one secondary thread so only one file can be downloaded at a time. Do exactly what you just said and it will work.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  13. #13

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    Quote Originally Posted by jmcilhinney View Post
    You can use a loop. There is only one secondary thread so only one file can be downloaded at a time. Do exactly what you just said and it will work.
    How would I go about doing so with this sub?

    Code:
    Public Sub CallWorker()
            Dim colFiles As New Collection
            Dim intCtr As Integer
    'the collection
            colFiles.Add("GitPortable.zip")
            colFiles.Add("ArduPilot-Arduino-1.0.3-windows.zip")
            colFiles.Add("MHV_AVR_Tools_20121007.exe")
    'the loop
            For intCtr = 1 To colFiles.Count
    
                If System.IO.File.Exists("C:\Windows\Temp\MPNGTemp\" & colFiles(intCtr)) Then
                    RichTextBox1.AppendText(colFiles(intCtr) & " Already exists so skipping" & vbCrLf)
                Else
                    Label5.Text = colFiles(intCtr)
                    RichTextBox1.AppendText(colFiles(intCtr) & " does not exist so downloading" & vbCrLf)
                    'Control.CheckForIllegalCrossThreadCalls = False
    'starts the progress bar
                    Timer1.Start()
    'starts the download sub
                    BackgroundWorker.RunWorkerAsync()
                End If
    'end of loop
            Next intCtr
        End Sub
    That is the loop I am using to call the backgroundworker.

    And it is calling this as the background worker

    Code:
    Private Sub Downloader_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker.DoWork
            'mod this
            Filename = Label5.Text
            File.Delete("C:\Windows\Temp\MPNGTemp\" & Filename)
            If Filename = "ArduPilot-Arduino-1.0.3-windows.zip" Then
                link = "http://www.sshcs.com/MPNG/ArduPilot-Arduino-1.0.3-windows.zip"
            ElseIf Filename = "GitPortable.zip" Then
                link = "http://www.sshcs.com/MPNG/GitPortable.zip"
            ElseIf Filename = "MHV_AVR_Tools_20121007.exe" Then
                link = "http://firmware.diydrones.com/Tools/Arduino/MHV_AVR_Tools_20121007.exe"
            ElseIf Filename = "" Then
                MsgBox("Error No File Passed")
            End If
    
            Try
                Dim size As Integer
                Dim wr As WebRequest
                wr = WebRequest.Create(link)
                Dim webr As WebResponse = wr.GetResponse
                size = webr.ContentLength
                size = size / 1024
                ProgressBar1.Maximum = size
                Label2.Text = size
                Dim wc As New WebClient
                wc.DownloadFile(link, "C:\Windows\Temp\MPNGTemp\" & Filename)
                RichTextBox1.AppendText("Finished downloading " & Filename & vbCrLf)
            Catch ex As Exception
            End Try
            Exit Sub
    Each by themselves work fine and both work fine together if say 2 of the files are already there [it doesn't matter which 2]

    How do I call a backgroundworker and halt any further execution of the sub until the initial loop finishes running and then running the 2nd loop and when it's done run the last loop?

  14. #14

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    I thought I was onto something

    Code:
    Public Sub CallWorker()
            Dim colFiles As New Collection
            Dim intCtr As Integer
            colFiles.Add("GitPortable.zip")
            colFiles.Add("ArduPilot-Arduino-1.0.3-windows.zip")
            colFiles.Add("MHV_AVR_Tools_20121007.exe")
    
            For intCtr = 1 To colFiles.Count
    
                If System.IO.File.Exists("C:\Windows\Temp\MPNGTemp\" & colFiles(intCtr)) Then
                    RichTextBox1.AppendText(colFiles(intCtr) & " Already exists so skipping" & vbCrLf)
                Else
                    Label5.Text = colFiles(intCtr)
                    RichTextBox1.AppendText(colFiles(intCtr) & " does not exist so downloading" & vbCrLf)
                    'Control.CheckForIllegalCrossThreadCalls = False
                    Timer1.Start()
                    'BackgroundWorker.RunWorkerAsync()
                    Try
                        'Start background worker
                        BackgroundWorker.RunWorkerAsync()
                        While BackgroundWorker.IsBusy()
                            Windows.Forms.Application.DoEvents()
                        End While
    
                        'Voila, we are back in sync
                        RichTextBox1.AppendText("Success!" & vbCrLf)
                    Catch ex As Exception
                        'MsgBox("Oops!" & vbCrLf & ex.Message)
                    End Try
                End If
            Next intCtr
    and while it does seem to do "something" it doesn't actually download anything lol

  15. #15
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: BackgroundWorker problem

    Get rid of that CallWorker method entirely. When the user clicks the Button, just call RunWorkerAsync and that's it. Now, in the DoWork event handler, create your list of URLs and loop through it. Done!

    As I have already said, DO NOT touch any controls in the DoWork event handler. If you want to update the UI then do so ONLY in the ProgressChanged and/or RunWorkerCompleted event handler.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  16. #16

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    Quote Originally Posted by jmcilhinney View Post
    Get rid of that CallWorker method entirely. When the user clicks the Button, just call RunWorkerAsync and that's it. Now, in the DoWork event handler, create your list of URLs and loop through it. Done!

    As I have already said, DO NOT touch any controls in the DoWork event handler. If you want to update the UI then do so ONLY in the ProgressChanged and/or RunWorkerCompleted event handler.
    I kind of get what you're saying, but in doing that I lose my working progress bar and bytes and size on my form no?

  17. #17
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: BackgroundWorker problem

    Quote Originally Posted by thequestor View Post
    I kind of get what you're saying, but in doing that I lose my working progress bar and bytes and size on my form no?
    Um, no.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  18. #18

    Thread Starter
    Member
    Join Date
    Jul 2011
    Posts
    51

    Re: BackgroundWorker problem

    I'm giving up
    I removed callworker

    I moved my loop into downloader_dowork

    but as I thought I had to remove everything that would update my progressbar and labels [like you said remove gui stuff] else it errors like mad

    I ended up with this
    Code:
    Private Sub Downloader_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker.DoWork
      
            Dim colFiles As New Collection
            Dim intCtr As Integer
            colFiles.Add("GitPortable.zip")
            colFiles.Add("ArduPilot-Arduino-1.0.3-windows.zip")
            colFiles.Add("MHV_AVR_Tools_20121007.exe")
    
            For intCtr = 1 To colFiles.Count
    
                If System.IO.File.Exists("C:\Windows\Temp\MPNGTemp\" & colFiles(intCtr)) Then
                    'RichTextBox1.AppendText(colFiles(intCtr) & " Already exists so skipping" & vbCrLf)
                Else
                    'Label5.Text = colFiles(intCtr)
                    'RichTextBox1.AppendText(colFiles(intCtr) & " does not exist so downloading" & vbCrLf)
                    'Timer1.Start()
                    Filename = colFiles(intCtr)
    
    
                    If Filename = "ArduPilot-Arduino-1.0.3-windows.zip" Then
                        link = "http://www.sshcs.com/MPNG/ArduPilot-Arduino-1.0.3-windows.zip"
                    ElseIf Filename = "GitPortable.zip" Then
                        link = "http://www.sshcs.com/MPNG/GitPortable.zip"
                    ElseIf Filename = "MHV_AVR_Tools_20121007.exe" Then
                        link = "http://firmware.diydrones.com/Tools/Arduino/MHV_AVR_Tools_20121007.exe"
                    ElseIf Filename = "" Then
                        MsgBox("Error No File Passed")
                    End If
                    File.Delete("C:\Windows\Temp\MPNGTemp\" & Filename)
                    Try
                        Dim size As Integer
                        Dim wr As WebRequest
                        wr = WebRequest.Create(link)
                        Dim webr As WebResponse = wr.GetResponse
                        size = webr.ContentLength
                        size = size / 1024
                        'ProgressBar1.Maximum = size
                        'Label2.Text = size
                        Dim wc As New WebClient
                        wc.DownloadFile(link, "C:\Windows\Temp\MPNGTemp\" & Filename)
                        'RichTextBox1.AppendText("Finished downloading " & Filename & vbCrLf)
                    Catch ex As Exception
    
                    End Try
                End If
            Next intCtr
            Exit Sub
        End Sub
    and it "does" download each file and skips any that are already there but like I said above I lose my progress bar and labels updating and
    at the end it tosses an error that says I have to remove my just in time debugger to see the error but what I seem to see is it is a crossthreading issue.

    sigh.

    I'm just going to run 3 routines to do this.

  19. #19
    Addicted Member
    Join Date
    Oct 2012
    Location
    Springfield, IL
    Posts
    142

    Re: BackgroundWorker problem

    Sorry my other suggestion didn't work for you since you're trying to support XP

    I wrote a little test code that runs a loop and calls a method that creates a new Backgroundworker each time.
    All of the event handlers for the BackgroundWorker are self contained in the DoWorkAsync method.

    Try it and see if it might help you create what you want.

    Add a Form to the project and 1 Button and a RichTextBox to the form

    Name:  Screenshot (79).png
Views: 1047
Size:  10.8 KB
    vb.net Code:
    1. Imports System.ComponentModel
    2. Public Class Form1
    3.  
    4.     Private _cancelToken As Boolean
    5.  
    6.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7.         Me.RichTextBox1.Clear()
    8.         _cancelToken = False
    9.         For i = 1 To 10
    10.             Dim name = "Thread " & i.ToString
    11.             DoWorkAsync(name)
    12.         Next
    13.     End Sub
    14.  
    15.     ' Create any parameters needed to download your file.
    16.     Private Sub DoWorkAsync(threadName As String)
    17.  
    18.         ' fresh new BackgroundWorker is created each time.
    19.         Dim worker As New BackgroundWorker
    20.         worker.WorkerReportsProgress = True
    21.  
    22.         AddHandler worker.DoWork,
    23.             Sub(s, e)
    24.                         ' do not access UI controls or update UI
    25.                         ' controls from within worker.DoWork
    26.                         Dim w = DirectCast(s, BackgroundWorker)
    27.  
    28.                         'Dim wc As New System.Net.WebClient
    29.                         'wc.DownloadFile("someinternetaddress", "someFileName")
    30.  
    31.                         For i = 1 To 10
    32.                             'If _cancelToken = true Then
    33.                             '    Exit For
    34.                             'Else
    35.                             Threading.Thread.Sleep(500) 'simulate long running task.
    36.                             w.ReportProgress(i * 10)
    37.                             'End If
    38.                         Next
    39.                     End Sub
    40.  
    41.         AddHandler worker.ProgressChanged,
    42.             Sub(s, e)
    43.                         ' Safe to update UI from here.
    44.                         Me.RichTextBox1.AppendText(threadName & " is at " & e.ProgressPercentage & "%." & Environment.NewLine)
    45.                     End Sub
    46.  
    47.         AddHandler worker.RunWorkerCompleted,
    48.             Sub(s, e)
    49.                         ' Safe to update UI from here.
    50.                         Me.RichTextBox1.AppendText(threadName & " RunWorkercompleted!" & Environment.NewLine)
    51.                     End Sub
    52.  
    53.         ' Start the asynchrouous operation.
    54.         worker.RunWorkerAsync()
    55.  
    56.  
    57.     End Sub
    58.  
    59. End Class



    Sigh... I just read that you dont want the downloads to run concurrent.

    Edit:
    Ok I just reconfigured the code to use an Queue to fire each BackgroundWorker successive order.

    Edited and removed the use of the Tuple

    Name:  Screenshot (80).png
Views: 930
Size:  8.0 KB

    vb.net Code:
    1. Imports System.ComponentModel
    2. Public Class Form1
    3.  
    4.     Private _cancelToken As Boolean
    5.     Private _actionQueue As New Queue(Of Action)
    6.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7.         If Me._actionQueue.Count > 0 Then Exit Sub
    8.         Me.RichTextBox1.Clear()
    9.         Me._actionQueue.Clear()
    10.         _cancelToken = False
    11.         For i = 1 To 10
    12.             Dim name = "Thread " & i.ToString
    13.             ' Create an action and place it in the queue
    14.             _actionQueue.Enqueue(CreateWorkerItem(name))
    15.         Next
    16.         ' Dequeue the Action and invoke it.
    17.         _actionQueue.Dequeue().Invoke()
    18.     End Sub
    19.  
    20.     ' Create any parameters needed to download your file.
    21.     Private Function CreateWorkerItem(threadName As String) As Action
    22.  
    23.         Dim myAction = New Action(
    24.             Sub()
    25.  
    26.                 ' fresh new BackgroundWorker is created each time.
    27.                 Dim worker As New BackgroundWorker
    28.                 worker.WorkerReportsProgress = True
    29.                 worker.WorkerSupportsCancellation = True
    30.                 AddHandler worker.DoWork,
    31.                     Sub(s, e)
    32.                         ' do not access UI controls or update UI
    33.                         ' controls from within worker.DoWork
    34.                         Dim w = DirectCast(s, BackgroundWorker)
    35.  
    36.                         'Dim wc As New System.Net.WebClient
    37.                         'wc.DownloadFile("someinternetaddress", "someFileName")
    38.  
    39.                         For i = 1 To 10
    40.                             'If _cancelToken = True Then
    41.                             '    w.CancelAsync()
    42.                             'Else
    43.                             Threading.Thread.Sleep(100) 'simulate long running task.
    44.                             'If _cancelToken = True Then w.CancelAsync()
    45.                             w.ReportProgress(i * 10)
    46.                             'End If
    47.                         Next
    48.                     End Sub
    49.  
    50.                 AddHandler worker.ProgressChanged,
    51.                     Sub(s, e)
    52.                         ' Safe to update UI from here.
    53.                         Me.RichTextBox1.AppendText(threadName & " is at " & e.ProgressPercentage & "%." & Environment.NewLine)
    54.                         Me.RichTextBox1.ScrollToCaret()
    55.                     End Sub
    56.  
    57.                 AddHandler worker.RunWorkerCompleted,
    58.                     Sub(s, e)
    59.                         ' Safe to update UI from here.
    60.  
    61.                         Me.RichTextBox1.AppendText(threadName & " RunWorkercompleted!" & Environment.NewLine)
    62.                         Me.RichTextBox1.ScrollToCaret()
    63.                         ' Dequeue the next item in the queue.
    64.                         If _actionQueue.Count > 0 Then
    65.                             _actionQueue.Dequeue().Invoke()
    66.                         Else
    67.                             _actionQueue.Clear()
    68.                         End If
    69.  
    70.                     End Sub
    71.  
    72.                 ' Start the asynchrouous operation.
    73.                 worker.RunWorkerAsync()
    74.  
    75.             End Sub)
    76.  
    77.         ' Return a tuple to hold the Action and the ThreadName parameter.
    78.         Return myAction
    79.  
    80.     End Function
    81.  
    82. End Class
    Last edited by OICU812; Mar 28th, 2014 at 04:50 PM.

  20. #20
    Addicted Member
    Join Date
    Oct 2012
    Location
    Springfield, IL
    Posts
    142

    Re: BackgroundWorker problem

    I see in your last code where you did like jmcilhinney suggested and loop inside the DoWork event that you would never be able to update your labels until the very end when the BackGroundWorker fires the RunWorkerCompleted event. However, you probably could pass whatever information between each loop to the reportProgress UserState object and work out the messages for the labels in the ProgressChanged event.

    My Last post above here could be simplified and not have to used the Tuple or have to carry the arguments with the Queue. All it needs to be is a Queue(of Action). It works pretty slick, I never messed with programming this way but I learned something new in the process.

  21. #21
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: BackgroundWorker problem

    A more simpler if thats to confusing

    vb Code:
    1. Imports System.Net
    2.  
    3. Public Class MainForm
    4.  
    5.     Private ReadOnly temp As String = "http://download.piriform.com/ccsetup327.exe"
    6.     Private m_dictionary As New Dictionary(Of WebClient, String)
    7.  
    8.     Private Sub Download(ByVal Path As String, ByVal FileName As String)
    9.         Dim client As New WebClient
    10.         Dim file As String = IO.Path.Combine(Path, FileName)
    11.  
    12.         AddHandler client.DownloadProgressChanged, AddressOf DownloadProgressChanged
    13.         AddHandler client.DownloadFileCompleted, AddressOf DownloadFileCompleted
    14.  
    15.         client.DownloadFileAsync(New Uri(temp), file)
    16.         Me.m_dictionary.Add(client, file)
    17.     End Sub
    18.  
    19.     Private Sub DownloadProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)
    20.         Dim file As String = m_dictionary.Item(CType(sender, WebClient))
    21.         Me.RichTextBox1.AppendText(String.Format("File {0} {1}{2}", file, e.ProgressPercentage & "%", vbNewLine))
    22.         Me.RichTextBox1.ScrollToCaret()
    23.     End Sub
    24.  
    25.     Private Sub DownloadFileCompleted(ByVal sender As Object, _
    26.                                                        ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
    27.         Dim client As WebClient = DirectCast(sender, WebClient)
    28.         client.Dispose()
    29.         m_dictionary.Remove(client)
    30.     End Sub
    31.  
    32. End Class
    My Github - 1d3nt

  22. #22
    Addicted Member
    Join Date
    Oct 2012
    Location
    Springfield, IL
    Posts
    142

    Re: BackgroundWorker problem

    Quote Originally Posted by ident View Post
    A more simpler if thats to confusing

    vb Code:
    1. Imports System.Net
    2.  
    3. Public Class MainForm
    4.  
    5.     Private ReadOnly temp As String = "http://download.piriform.com/ccsetup327.exe"
    6.     Private m_dictionary As New Dictionary(Of WebClient, String)
    7.  
    8.     Private Sub Download(ByVal Path As String, ByVal FileName As String)
    9.         Dim client As New WebClient
    10.         Dim file As String = IO.Path.Combine(Path, FileName)
    11.  
    12.         AddHandler client.DownloadProgressChanged, AddressOf DownloadProgressChanged
    13.         AddHandler client.DownloadFileCompleted, AddressOf DownloadFileCompleted
    14.  
    15.         client.DownloadFileAsync(New Uri(temp), file)
    16.         Me.m_dictionary.Add(client, file)
    17.     End Sub
    18.  
    19.     Private Sub DownloadProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)
    20.         Dim file As String = m_dictionary.Item(CType(sender, WebClient))
    21.         Me.RichTextBox1.AppendText(String.Format("File {0} {1}{2}", file, e.ProgressPercentage & "%", vbNewLine))
    22.         Me.RichTextBox1.ScrollToCaret()
    23.     End Sub
    24.  
    25.     Private Sub DownloadFileCompleted(ByVal sender As Object, _
    26.                                                        ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
    27.         Dim client As WebClient = DirectCast(sender, WebClient)
    28.         client.Dispose()
    29.         m_dictionary.Remove(client)
    30.     End Sub
    31.  
    32. End Class
    Don't forget to call RemoveHandler for each WebClient or otherwise they will not get G.C.'d

  23. #23
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,401

    Re: BackgroundWorker problem

    Of course, but also i should be using the "using statement". I can't write the whole project for them. I also never include try catch in my examples.
    My Github - 1d3nt

Tags for this Thread

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