BackgroundWorker - ProgressChanged & ProgressBar not working.
BackgroundWorker - ProgressChanged & ProgressBar not working.
BackgroundWorker - ProgressChanged & ProgressBar not working.
BackgroundWorker - ProgressChanged & ProgressBar not working.
BackgroundWorker - ProgressChanged & ProgressBar not working.
BackgroundWorker - ProgressChanged & ProgressBar not working. BackgroundWorker - ProgressChanged & ProgressBar not working. BackgroundWorker - ProgressChanged & ProgressBar not working. BackgroundWorker - ProgressChanged & ProgressBar not working. BackgroundWorker - ProgressChanged & ProgressBar not working. BackgroundWorker - ProgressChanged & ProgressBar not working. BackgroundWorker - ProgressChanged & ProgressBar not working. BackgroundWorker - ProgressChanged & ProgressBar not working.
BackgroundWorker - ProgressChanged & ProgressBar not working. BackgroundWorker - ProgressChanged & ProgressBar not working.
BackgroundWorker - ProgressChanged & ProgressBar not working.
Go Back  Xtreme Visual Basic Talk > > > BackgroundWorker - ProgressChanged & ProgressBar not working.


Reply
 
Thread Tools Display Modes
  #1  
Old 03-05-2008, 08:50 AM
VanishingHope VanishingHope is offline
Freshman
 
Join Date: Jan 2007
Location: Pittsburgh, PA
Posts: 34
Default BackgroundWorker - ProgressChanged & ProgressBar not working.


Hi everyone,

I've searched this forum and the Internet once over to try and fix my problem. To sum things up, I have a BackgroundWorker and a long-running method, which I want to update a progress bar on my form.

The BackgroundWorker does its job. The only issue is that the line ProgressBar1.Value = e.ProgressPercentage() does not update the Progress Bar. Oh, I have set the BackgroundWorker to allow progress reporting in its properties.

Any help is greatly appreciated.
Thank you for your time.
--VH

Here's my BackgroundWorker event methods.
Code:
Imports System.ComponentModel
...
Private Sub BackgroundWorker1_DoWork( _
     ByVal sender As System.Object, _
     ByVal e As System.ComponentModel.DoWorkEventArgs) _
     Handles BackgroundWorker1.DoWork
        Dim returnValue As Integer

        Select Case e.Argument()
            Case Is = 1
                lblCurrentTask.Text = "Cleaning Archive Logs..."
                MenuStrip1.Enabled = False
                returnValue = cleanArchiveLogs()
                Exit Select
            Case Is = 2
                lblCurrentTask.Text = "Sorting the Success Folder..."
                MenuStrip1.Enabled = False
                returnValue = sortSuccess()
                Exit Select
            Case Is = 3
                lblCurrentTask.Text = "Gathering Statistics on the Success Folder..."
                MenuStrip1.Enabled = False
                returnValue = statSuccess()
                Exit Select
        End Select

End Sub
Code:
Private Sub BackgroundWorker1_ProgressChanged( _
     ByVal sender As Object, _
     ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
     Handles BackgroundWorker1.ProgressChanged
          'e.ProgressPercentage is passed correctly.  Using Debug.Print()
          'I'm able to see e.ProgressPercentage is correct.
          'However, the progress bar does not get updated.
          ProgressBar1.Value = CInt(e.ProgressPercentage)
End Sub
Code:
Private Sub BackgroundWorker1_RunWorkerCompleted( _
     ByVal sender As Object, _
     ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
     Handles BackgroundWorker1.RunWorkerCompleted
          ProgressBar1.Value = 0
          lblCurrentTask.Text = lblCurrentTask.Text + " Completed."
          MenuStrip1.Enabled = True
End Sub
Here's one of my methods (the shortest) which works the exact same for reporting progress. One thing to mention is that this method is in a separate module and not in the form itself.

Code:
Public Function cleanArchiveLogs() As Integer
     Dim fileList() As String
     Dim count As Long
     Dim fileWriteTime As Date
     Dim totalFiles As Integer

     count = 0

     fileList = IO.Directory.GetFiles(dirArchLog, "*.*", _
          IO.SearchOption.TopDirectoryOnly)

     'Used in calculating percentage complete
     totalFiles = Cint(UBound(fileList) / 100)

     Do While count <= UBound(fileList)
          fileWriteTime = IO.File.GetLastWriteTime(fileList(count))

          If DateDiff(DateInterval.Day, fileWriteTime, Now()) > 21 Then
               IO.File.Delete(fileList(count))
          End If

          count += 1

          If (count Mod totalFiles) = 0 Then
               'This actually does sent a value to the ReportProgress event.
               'However, the ProgressBar1.Value = does nothing.
               formMain.BackgroundWorker1.ReportProgress(count / totalFiles)
          End If
     Loop

     formMain.BackgroundWorker1.ReportProgress(100)
End Function
Reply With Quote
  #2  
Old 03-05-2008, 09:28 AM
AtmaWeapon's Avatar
AtmaWeaponBackgroundWorker - ProgressChanged &amp; ProgressBar not working. AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Always, always use a debugger and look over what's happening to your variables. If you had used the debugger, you'd have solved this problem hours ago.

You want to express count vs. total files as a percentage, so you set totalFiles to (files / 100), and therefore your progress comes out to:
count / (number of files / 100)

This simplifies to:
(count * 100) / (number of files)

... which surprised me by being correct. Due to the order of operations, something different entirely happens anyway. Suppose there are 50 files. The line totalFiles = Cint(UBound(fileList) / 100) will be interpreted as totalFiles = CInt(49 / 100). 49 / 100 = 0.49, which is then truncated to 0. Now, we have a divide by 0 error.

What if there's 200 files? totalFiles will be set to CInt(200 / 100), which is 2. When we're on file 1, progress will be 1/2, or 50%. Obviously this is not what you want.

In actuality, due to the If statement you might never send a progress report. It will only be sent when the total number of files can be described by (multiple of 100) + 1, and then only on one iteration of your loop.

totalFiles should be the number of files in the file list; the Length of the array rather than its upper bound. Do not divide this value by 100. The proper way to express this line would be:
totalFiles = fileList.Length

The final change is that the percentage must be an integer in the range 0-100, but count / totalFiles should be a double in the range 0-1. The percentage can be calculated using the formula CInt((count / totalFiles) * 100), which is identical to the result above ((count * 100) / totalFiles). It's much more clear if you delay the multiplication by 100 until the end.

I suspect your other methods make similar errors. Use the debugger and I'm sure you'll find you're sending oddball values to the progress bar.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #3  
Old 03-05-2008, 11:13 AM
VanishingHope VanishingHope is offline
Freshman
 
Join Date: Jan 2007
Location: Pittsburgh, PA
Posts: 34
Default

Thank you for the help on the math part. I was actually using Mod before to get the information and was passing the correct percentage. However, I made some modifications just before posting and did not debug that time.

The only problem is, my Progress bar will still not visibly change. I've made sure it's Visible, it's enabled and rechecked its value after I set it using both of the examples below. Its value does change because I can the get its value and it is set to the new percentage.

I've tried the direct change via ProgressChanged:
Code:
Private Sub BackgroundWorker1_ProgressChanged( _
     ByVal sender As Object, _
     ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
     Handles BackgroundWorker1.ProgressChanged
          ProgressBar1.Value = CInt(e.ProgressPercentage)
End Sub
I've also tried this:
Code:
Public Delegate Sub progressUpdateCallback(ByVal percent As Integer)

Private Sub progressUpdate(ByVal percent As Integer)
     If Me.ProgressBar1.InvokeRequired Then
          Dim d As New progressUpdateCallback(AddressOf progressUpdate)
          Me.Invoke(d, New Object() {percent})
     Else
          Me.ProgressBar1.Value = percent
     End If
End Sub

Private Sub BackgroundWorker1_ProgressChanged( _
     ByVal sender As Object, _
     ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
     Handles BackgroundWorker1.ProgressChanged
          Me.progressUpdate(e.ProgressPercentage)
End Sub
Reply With Quote
  #4  
Old 03-05-2008, 01:05 PM
AtmaWeapon's Avatar
AtmaWeaponBackgroundWorker - ProgressChanged &amp; ProgressBar not working. AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

I didn't see this part before:
Code:
One thing to mention is that this method is in a separate module and not in the form itself.
Are we absolutely sure that the formMain the module is referencing is the right form? Try adding this to your Load event handler:
Code:
Debug.WriteLine(String.Format("My handle is {0}.", Me.Handle.ToString())
And output the handle of formMain the same way before you use it; are they the same? If not, that's the problem.

It really sounds kind of like you are updating some form (since the debugger is showing correct values), but not the one that is visible.

If this isn't the case, can you create a new project with a minimal amount of code that reproduces this problem? I just tried making a form that uses a BackgroundWorker and had no troubles; I'm going to try modifying it to handle the events in a module and see if that has an effect.
Reply With Quote
  #5  
Old 03-05-2008, 01:38 PM
VanishingHope VanishingHope is offline
Freshman
 
Join Date: Jan 2007
Location: Pittsburgh, PA
Posts: 34
Default

Again, thank you for your help.

The handles were different. I moved the module's code over to formMain code, the handles were the same and now my progress bar works.

I figured that "sender" must have a reference to the form (and there-by handle) that initiated the BackgroundWorker1.

Here's the changes I made to my BackgroundWork_DoWork...
Code:
Private Sub BackgroundWorker1_DoWork( _
     ByVal sender As System.Object, _
     ByVal e As System.ComponentModel.DoWorkEventArgs) _
     Handles BackgroundWorker1.DoWork
          Dim returnValue As Integer
          Dim worker As System.ComponentModel.BackgroundWorker _
          = CType(sender, System.ComponentModel.BackgroundWorker)

          Select Case e.Argument()
               Case Is = backgroundWork.cleanArchiveLogs
                    Me.setText("Cleaning Archive Logs...")
                    Me.setMenu(False)
                    returnValue = cleanArchiveLogs(worker)
                    Exit Select
          ...
Then I change my method in the other module to...
Code:
Public Function cleanArchiveLogs( _
     ByVal worker As System.ComponentModel.BackgroundWorker) As Integer
...
'changed my progress report to this from...
'formMain.BackgroundWorker1.ReportProgress(percent)
'To...
worker.ReportProgress(percent)
..
End Function
My progress bar then works.

AtmaWeapon... thank you very much for your help on this! It is greatly appreciated.

--VH
Reply With Quote
  #6  
Old 06-04-2008, 06:06 AM
athar_anis athar_anis is offline
Newcomer
 
Join Date: Jun 2008
Posts: 1
Default Backgroundworker - Progressbar not running simultaneously

hi AtmaWeapon...
i have read this post and want to ask you something,

The problem is that i m exporting the data of one Excel Sheet to SQL Server using SQLBULKcopy. It is a huge data therefore it is taking long to copy to SQL Server. I want to show the copy progress in a progress bar.

till now, the progress bar is working fine.. but i m sure it is not showing the progress of the copying process itself. it is running the UPLOADPROCESS() function first and after it is done, it is displaying the progress in the progressbar.

heres my code.

Private Sub uploadProcess()

Dim myobj As New connectMyDB
myobj.conn.Open()

'Declare Variables
Dim sSQLTable As String = "temp"
Dim sExcelFileName As String = txt_excel_filepath.Text
Dim sWorkbook As String = "[" & txt_sheet_name.Text & "$]"

'Create our connection strings
Dim sExcelConnectionString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " & sExcelFileName & ";Extended Properties=""Excel 8.0;HDR=YES;"""
Dim sSqlConnectionString As String = myobj.conn.ToString


'Execute a query to erase any previous data from our destination table
Dim sClearSQL = "DELETE FROM " & sSQLTable

Dim SqlCmd As SqlCommand = New SqlCommand(sClearSQL, myobj.conn)
SqlCmd.ExecuteNonQuery()

'Series of commands to bulk copy data from the excel file into our SQL table
Dim OleDbConn As OleDbConnection = New OleDbConnection(sExcelConnectionString)
Dim OleDbCmd As OleDbCommand = New OleDbCommand(("SELECT * FROM " & sWorkbook), OleDbConn)

OleDbConn.Open()
Dim dr As OleDbDataReader

Try
dr = OleDbCmd.ExecuteReader()

Catch ex As Exception
MsgBox("No Sheet was found with the name: " & "'" & txt_sheet_name.Text & "'" & vbNewLine & "Aborting Upload Process...", MsgBoxStyle.Information, "Sheet Name Not Found")
Exit Sub

End Try

Dim bulkCopy As SqlBulkCopy = New SqlBulkCopy(myobj.conn)
bulkCopy.DestinationTableName = sSQLTable
Try
bulkCopy.WriteToServer(dr)
Catch ex As Exception
MsgBox("Error Occured. " & vbNewLine & "Error Description: " & Err.Description, MsgBoxStyle.Critical, "Error During Upload")

Exit Sub
End Try


OleDbConn.Close()
End Sub



Heres the button click routine:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_upload.Click
Try
worker.RunWorkerAsync()

Label4.Text = "Instructions Recieved...."
Label5.Text = "Reading File.... Please Wait !!!"
Catch ex As Exception
Exit Sub
End Try

End Sub

'The Background Worker Routine
Private Sub worker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles worker.DoWork
uploadProcess()
Dim I As Integer
For I = 1 To 100
System.Threading.Thread.Sleep(50)
worker.ReportProgress(I)
Next
End Sub


Private Sub worker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles worker.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
Label2.Text = e.ProgressPercentage & "%"
If e.ProgressPercentage = 1 Then
Label4.Text = ""
Label5.Text = "Processing Upload .... !!!"
ElseIf e.ProgressPercentage = 100 Then
Label4.Text = ""
Label5.Text = "Upload Successful..."
End If
End Sub




I have seriously given it atleast 2 days but i cant achieve the goal. everything is working fine. but i know that the progress bar is updating after the uploadProcess() routine is finished running.

whenever i run the application and click button1, it would make me wait for atleast 20 seconds (i think, its the time when its actually copying the Excel contents to SQL Server) and after its done, the progress bar starts its counter.

Is there anyway to run the SqlBulkCopy process and in the meanwhile see how much data has been copied ? and show it in the progress bar?

your kind help will be highly appreciated.
Thanks
Athar Anis
Reply With Quote
  #7  
Old 06-04-2008, 08:52 AM
AtmaWeapon's Avatar
AtmaWeaponBackgroundWorker - ProgressChanged &amp; ProgressBar not working. AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

SqlBulkCopy is a synchronous method that provides no feedback as to its progress. This means you're not going to be able to give any indication as to how far along it is. There may be an API solution, but I would figure the best way to do this would be to forget about the SqlBulkCopy object and manually send each row to the server. An alternative would be to set the progress bar's Style property to Marquee to indicate an indeterminate time for completion; unfortunately this is only supported on XP and later and only if Visual Styles are turned on.

In my opinion, your best bet is to display some form of indeterminate progress indicator during the upload process (a simple dialog stating "Updating database, this may take a few minutes..." would do).

Also, in the future, please start a new thread for new questions rather than take over an old one; I wasted a few minutes reviewing the past posts under the mistaken assumption that the original poster had a new question. Additionally, please use the [code] tags to post code, it makes it much easier to read when it's indented.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #8  
Old 06-04-2008, 05:23 PM
MKoslof's Avatar
MKoslofBackgroundWorker - ProgressChanged &amp; ProgressBar not working. MKoslof is offline
Cum Grano Salis

Retired Moderator
* Guru *
 
Join Date: Jul 2002
Location: Baltimore, Maryland
Posts: 14,636
Default

Agreed, please start a new thread next time. Your best option here is to use the .NotifyAfter property which determines the number of rows to process before raising the SQLRowsCopied event. Then for example, if you are doing a long running copy, spawn this on a seperate thread and marshal back to the main STA thread to update a label and use a marquee progress bar as noted by Atma. Therefore you can have a response UI that updates a status label every x number of rows copied until done, etc. However, I have found this process while decently quick, is a memory hog and I tend to like to do my Bulk Inserts at the SQL Server level or let the SQL Server itself take the bulk of the memory hit, etc. Such as using the Service Broker (if SQL Server 2005) to spawn off the process asyncronously within SQL Server itself, etc
__________________
"Artificial Intelligence is no match for natural stupidity." ~unknown
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
BackgroundWorker - ProgressChanged &amp; ProgressBar not working. BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
BackgroundWorker - ProgressChanged &amp; ProgressBar not working. BackgroundWorker - ProgressChanged &amp; ProgressBar not working. BackgroundWorker - ProgressChanged &amp; ProgressBar not working. BackgroundWorker - ProgressChanged &amp; ProgressBar not working. BackgroundWorker - ProgressChanged &amp; ProgressBar not working. BackgroundWorker - ProgressChanged &amp; ProgressBar not working. BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
 
BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
BackgroundWorker - ProgressChanged &amp; ProgressBar not working.
 
-->