By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,740 Members | 844 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,740 IT Pros & Developers. It's quick & easy.

probleum in running the thread program

P: 40
Hi!
i am making a program invb.net on threading but when i execute it produce the error on the progbar.Value = newval
my program is
Imports System.Threading
Public Class Form1
Private trd As Thread
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MsgBox("this is main thread")
End Sub
Private Sub threadtask()
Dim stp As Integer
Dim newval As Integer
Dim rnd As New Random()
Do
stp = progbar.Step * rnd.Next(-1, 2)
newval = progbar.Value + stp
If newval > progbar.Maximum Then
newval = progbar.Maximum
ElseIf newval < progbar.Minimum Then
newval = progbar.Minimum
End If

progbar.Value = newval here is error and error is
Cross-thread operation not valid: Control 'progbar' accessed from a thread other than the thread it was created on.
Thread.Sleep(100)
Loop
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
trd = New Thread(AddressOf threadtask)
trd.IsBackground = True
trd.Start()

End Sub
End Class
Mar 29 '08 #1
Share this Question
Share on Google+
1 Reply


balabaster
Expert 100+
P: 797
You cannot reference any property belonging to your form or objects on your form from any thread other than the main GUI thread. There are two methods you can use to achieve this:

First method (in my opinion, this should never be used, but as I said, that's just my opinion): There is an option somewhere in Visual Studio that allows you to turn off this feature - which allows for potentially fatal scenarios. It will then stop complaining about this and allow multiple threads to update form/object properties. I forget what it's called - but usually the error message tells you.

The Second method (and in my opinion should always be the one that is used) is to use delegates. Delegates are a bit tough to get your head around, but I will do my best to explain. Firstly I'll give a code example and then I'll explain what it's doing:
Expand|Select|Wrap|Line Numbers
  1. Private Delegate Sub MyMethodDelegate(ByVal ControlName As String, ByVal MyParam As String)
  2.  
  3. Private Sub MyActualMethod(ByVal ControlName As String, ByVal MyParam As String)
  4.     If Me.InvokeRequired Then
  5.         Dim oDlg As New MyMethodDelegate(AddressOf MyActualMethod)
  6.         Me.Invoke(oDlg, ControlName, MyParam)
  7.     Else
  8.         Me.Controls(ControlName).Text = MyParam
  9.     End If
  10. End Sub
  11.  
  12. Private Sub MyWorkerThread(ByVal Args As Object)
  13.     MyActualMethod("TextBox1", CType(Args, String))
  14. End Sub
  15.  
  16. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  17.     Dim oThreadArgs As Object = "Hello World"
  18.     Dim oThr As New Threading.Thread(AddressOf MyWorkerThread)
  19.     oThr.Start(oThreadArgs)
  20. End Sub
Okay, in my form load, I'm spinning off a thread that references the method MyWorkerThread which posts a string that I've passed in my thread start mechanism into the text box.

MyWorkerThread makes a call to the method called MyActualMethod which does a check to see if the form requires me to invoke (i.e. put this call on some call stack waiting for the form to synchronize threads) or if I can directly affect the change on my control. If you make a call to MyActualMethod from within your form directly, you will notice that when you step through the code, when you get into the MyActualMethod it always goes to the Else portion of your If statement. If you call it from your thread, it will always go through the If side of your statement a bunch of times before it goes to through the Else side...this is the system waiting for a safe slot to update the control.

On to the Delegate routine. In the If side of your statement you will notice that we've instantiated the delegate just like we would have any other object or variable - Dim oDlg As New Delegate...

The parameter we pass is a method address. What this is doing is running off behind the scenes is saying - "what memory address holds the block of code for the method with this name?" What we are effectively doing is this: We instantiate the delegate and tell it that when it is invoked, it must run the code contained within the method called MyActualMethod.

When MyActualMethod is called from a thread, it may go through this loop several times before it finds a safe slot in which to actually write the value into the textbox...if it doesn't find a safe slot, it will keep invoking the delegate (which in effect, is calling itself).

If you call MyActualMethod from the form itself, it never calls the delegate.
Mar 29 '08 #2

Post your reply

Sign in to post your reply or Sign up for a free account.