-2

I have a main form with a progressbar at the bottom status strip. It is set to marquee style. I want it to keep animating when I run a long function. But when the function hits, the form and everything on it freezes, so II used a backgroundworker to run the long function. But this gave me the following error inside the MyClass.BigFunction() code.

Cross-thread operation not valid: Control 'frmMainNew' accessed from a thread other than the thread it was created on.

"frmMainNew" is the main form on which the progressbar and backgroundworker are. I pass the form as a parameter to the MyClass object when I initialize it.

This is the first time I am using backgroundworker, so what else do I need? I have already looked at these examples and tried them, but nothing works. (1, 2, 3, 4, 5, 6).

I have to use this for other functions too.

My code:

   Private WithEvents bgw As BackgroundWorker

Private Sub frmMainNew_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Try
        Me.SuspendLayout()

    'Other Functions

        w_AddBackgroundWorkerForProgressBar()

        Me.ResumeLayout()

    Catch ex As Exception
        Scube.Planner.ErrorHandler.DisplayError(ex)
    End Try

End Sub

Private Sub w_AddBackgroundWorkerForProgressBar()
    bgw = New BackgroundWorker
    AddHandler bgw.DoWork, AddressOf bgw_DoWork
    AddHandler bgw.RunWorkerCompleted, AddressOf bgw_Completed
    'AddHandler bgw.ProgressChanged, AddressOf bgw_ProgressChanged
End Sub

Private Sub MyButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyButton.Click
    Try

        bgw.WorkerSupportsCancellation = True
        bgw.RunWorkerAsync()
        'MyClass.BigFunction()   <--- Originally called from here
    Catch ex As Exception
        Scube.Planner.ErrorHandler.DisplayError(ex)
    Finally
        Me.Cursor = Cursors.Default
    End Try
End Sub

Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bgw.DoWork
    'Do your lenghty operations here

    MyClass.BigFunction()

    System.Threading.Thread.Sleep(10000)

End Sub

Private Sub bgw_Completed(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted
    If Not IsNothing(e.Error) Then
        MessageBoxEx.Show(e.Error.ToString)
    End If
    ProgressBar1.Hide()
End Sub

Private Sub w_ShowProgressBar()
    ProgressBar1.Show()
    Me.Refresh()
    System.Windows.Forms.Application.DoEvents()
End Sub
Community
  • 1
  • 1
Veda
  • 243
  • 1
  • 15
  • 1
    You have to call `w_ShowProgressBar()` from the main form or one of it's controls. If it's called by the BackgroundWorker or the `BigFunction()` it will not work because anything that is executed by a BackgroundWorker will be executed on a different thread, which means that no controls in the main form can be modified from that thread. So I'd recommend you to call the progressbar function on the button click event instead. – Visual Vincent Feb 20 '15 at 10:15

1 Answers1

0

You cant and should not access your frmMainNew from your 'BigFunction()'. It is working on a separate thread and does not have access to the UI thread. We need to see what you are doing inside your bigfunction to tell you the problem. Im going to take a guess and say you are trying to update the progressbar values from within that function? If this is so then is the incorrect way to do so.

What you need to do is, set the progress in your BigFunction like so:

bgw.ReportProgress(Progress/Percentage)

and have an event for the progress changed and inside of that event is where you update the progress bar.

Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
  Progressbar1.value = e.ProgressPercentage
End Sub
Mr Dog
  • 396
  • 1
  • 3
  • 22
  • I don't think we need to see anything more. It must be the progressbar since it's not called in any of the above code. _Move the `w_ShowProgressBar()` call out of BigFunction and into `MyButton_Click()`._ :) – Visual Vincent Feb 21 '15 at 00:06
  • The BigFunction does not have any progressbar or any other UI related code. It's just a rediculously complicated calculation function. We are adding a progress bar because it takes too long and the screen freezes while it's executing. I will try these suggestions. – Veda Feb 23 '15 at 08:46
  • Could you explain what you mean by this sentence--> "I pass the form as a parameter to the MyClass object when I initialize it." - How does your class interact with the form? And once you BigFunction is done processing, where does the results go? Are you using other objects/parameters in your class from the BigFunction? Also do you have code in your BigFunction to indicate progress being made? – Mr Dog Feb 23 '15 at 15:19
  • The calculation has lots of code and involves lots of information from three different forms and a few controls on the Main Form. Hence, it has it's own class and I pass the MainForm as a parameter in it's constructor. But I see what you mean. I wrote the ProgressChanged event in my MainForm. How can I access bgw from the MyClass unless I do this: ParentForm.bgw.ReportProgress(int)? – Veda Feb 27 '15 at 12:21
  • First try and find why that error is popping up. Comment out line by line, if necessary, any code in your myclass that is accessing any element on the form and go from there. – Mr Dog Feb 27 '15 at 13:54