Trouble with Cross thread control access

T

Ty

I have a project that fills a DB in the background using asyn
threading when the project loads. The issue is that I have a
progressbar, button, and lable that I am using to let the user know
that there is work being done so at the end of the task I want to hide
those items but I am getting the error "Cross-thread operation not
valid: Control accessed from a thread other than the thread it was
created on".

I am using the example from here.
http://www.aspfree.com/c/a/VB.NET/D...-Asynchronous-Programming-with-VB-NET-2005/3/

The controls are created in the main thread when the form loads.
I realize that I am missing something or not placing the code in the
correct place. Here is my code.

Private Sub Form3_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

btnrunonce_Click(sender, e)

End Sub


Private Sub btnrunonce_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnrunonce.Click

StartExecuteTaskAsync()

End Sub


'*******************************************TEMPLATE CODE FOR
ASYNC APP
PROCESSING******************************************************
Dim thExecuteTaskAsync As Thread = Nothing
Private Sub StartExecuteTaskAsync()
'clear existing thread
If Not thExecuteTaskAsync Is Nothing Then
thExecuteTaskAsync.Abort()
thExecuteTaskAsync.Join()
thExecuteTaskAsync = Nothing
End If
'start a new thread to execute the task asynchronously
thExecuteTaskAsync = New Thread(AddressOf ExecuteTaskAsync)
thExecuteTaskAsync.Start()
End Sub

Private Sub ExecuteTaskAsync()
MY TASK CODE IS HERE

btnGetComputers.Enabled = True *****ERROR THROWN
HERE*********************************
ColourProgressBar3.Visible = False
btnrunonce.Visible = False
lblFirst.Visible = False

End If

End With



End Sub

'================================================================
''DELEGATE declaration
Private Delegate Sub delShowStatus(ByVal i As String)
Dim ShowStatus As New delShowStatus(AddressOf ShowProgress)
Private Sub ShowProgress(ByVal i As String)
If ColourProgressBar3.Value <> 10 Then
ColourProgressBar3.Value = ColourProgressBar3.Value + 1
Else
ColourProgressBar3.Value = 0
End If
End Sub
'=============================================================


Private Sub Form3_FormClosing(ByVal sender As Object, ByVal e As
System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
'this is necessary if the form is trying to close, even before
the completion of task
If Not thExecuteTaskAsync Is Nothing Then
thExecuteTaskAsync.Abort()
End If
End Sub

Thanks,

Ty
 
T

Tom Shelton

I have a project that fills a DB in the background using asyn
threading when the project loads. The issue is that I have a
progressbar, button, and lable that I am using to let the user know
that there is work being done so at the end of the task I want to hide
those items but I am getting the error "Cross-thread operation not
valid: Control accessed from a thread other than the thread it was
created on".

I am using the example from here.
http://www.aspfree.com/c/a/VB.NET/D...-Asynchronous-Programming-with-VB-NET-2005/3/

The controls are created in the main thread when the form loads.
I realize that I am missing something or not placing the code in the
correct place. Here is my code.

Private Sub Form3_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

btnrunonce_Click(sender, e)

End Sub


Private Sub btnrunonce_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnrunonce.Click

StartExecuteTaskAsync()

End Sub


'*******************************************TEMPLATE CODE FOR
ASYNC APP
PROCESSING******************************************************
Dim thExecuteTaskAsync As Thread = Nothing
Private Sub StartExecuteTaskAsync()
'clear existing thread
If Not thExecuteTaskAsync Is Nothing Then
thExecuteTaskAsync.Abort()
thExecuteTaskAsync.Join()
thExecuteTaskAsync = Nothing
End If
'start a new thread to execute the task asynchronously
thExecuteTaskAsync = New Thread(AddressOf ExecuteTaskAsync)
thExecuteTaskAsync.Start()
End Sub

Private Sub ExecuteTaskAsync()
MY TASK CODE IS HERE

btnGetComputers.Enabled = True *****ERROR THROWN
HERE*********************************
ColourProgressBar3.Visible = False
btnrunonce.Visible = False
lblFirst.Visible = False

You can not access any controls directly in this method (while that's not 100%
true, there are a few methods/properties that are threadsafe - invoke,
begininvoke,endinvoke, invokerequired - to name a few)! ExecuteTaskAsync is
executing on a different thread. Any control related action that you need to
take need to be marshaled back to the main thread using Invoke... That's why
the example called the Invoke (ShowStatus, etc, etc)...


Though, it seems to me, you should probably just be using a backgroundWorker
component.
 
T

Tom Shelton

I have a project that fills a DB in the background using asyn
threading when the project loads. The issue is that I have a
progressbar, button, and lable that I am using to let the user know
that there is work being done so at the end of the task I want to hide
those items but I am getting the error "Cross-thread operation not
valid: Control accessed from a thread other than the thread it was
created on".

I am using the example from here.
http://www.aspfree.com/c/a/VB.NET/D...-Asynchronous-Programming-with-VB-NET-2005/3/

The controls are created in the main thread when the form loads.
I realize that I am missing something or not placing the code in the
correct place. Here is my code.

Private Sub Form3_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

btnrunonce_Click(sender, e)

End Sub


Private Sub btnrunonce_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnrunonce.Click

StartExecuteTaskAsync()

End Sub


'*******************************************TEMPLATE CODE FOR
ASYNC APP
PROCESSING******************************************************
Dim thExecuteTaskAsync As Thread = Nothing
Private Sub StartExecuteTaskAsync()
'clear existing thread
If Not thExecuteTaskAsync Is Nothing Then
thExecuteTaskAsync.Abort()
thExecuteTaskAsync.Join()
thExecuteTaskAsync = Nothing
End If
'start a new thread to execute the task asynchronously
thExecuteTaskAsync = New Thread(AddressOf ExecuteTaskAsync)
thExecuteTaskAsync.Start()
End Sub

Private Sub ExecuteTaskAsync()
MY TASK CODE IS HERE

btnGetComputers.Enabled = True *****ERROR THROWN
HERE*********************************
ColourProgressBar3.Visible = False
btnrunonce.Visible = False
lblFirst.Visible = False

You can not access any controls directly in this method (while that's not 100%
true, there are a few methods/properties that are threadsafe - invoke,
begininvoke,endinvoke, invokerequired - to name a few)! ExecuteTaskAsync is
executing on a different thread. Any control related action that you need to
take need to be marshaled back to the main thread using Invoke... That's why
the example called the Invoke (ShowStatus, etc, etc)...


Though, it seems to me, you should probably just be using a backgroundWorker
component.
 
N

nak

Hi Ty,

Private Delegate Sub delegatedCallbackDelegate(Byval iArg1 as String, Byval
iArg2 as Integer, Byval iArg3 as Object)

Private cDelDelegatedCallback as new delegatedCallbackDelegate(AddressOf
delegatedCallback)

Private Sub delegatedCallback(Byval iArg1 as String, Byval iArg2 as Integer,
Byval iArg3 as Object)
'//Do stuff here
End Sub


'//To invoke the method from the calling thread

Dim pObjParams() as Object = {"Arg1", 2, SomeObjectReference}
Call ControlOnTargetThread.Invoke(cDelDelegatedCallback, pObjParams)

....

Call Me.Invoke(cDelDelegatedCallback, pObjParams) //Presuming you are
in form code, this will cause the form to invoke, and as the form created
the control it should work


Nick.
 
N

nak

Hi Ty,

Private Delegate Sub delegatedCallbackDelegate(Byval iArg1 as String, Byval
iArg2 as Integer, Byval iArg3 as Object)

Private cDelDelegatedCallback as new delegatedCallbackDelegate(AddressOf
delegatedCallback)

Private Sub delegatedCallback(Byval iArg1 as String, Byval iArg2 as Integer,
Byval iArg3 as Object)
'//Do stuff here
End Sub


'//To invoke the method from the calling thread

Dim pObjParams() as Object = {"Arg1", 2, SomeObjectReference}
Call ControlOnTargetThread.Invoke(cDelDelegatedCallback, pObjParams)

....

Call Me.Invoke(cDelDelegatedCallback, pObjParams) //Presuming you are
in form code, this will cause the form to invoke, and as the form created
the control it should work


Nick.
 
T

Ty

Thanks for the info Nick.

I actually solved it by placing a module level boolean variable into
the Private Sub ExecuteTaskAsync() that is evaluated in the Private
Sub ShowProgress sub. Because I am using a For Next loop I can easily
tell when the task is complete then I simply set the variable and when
it hit the ShowProgress sub and evaluates the variable and sees the
change it runs the code to hide the controls which I moved to the
ShowProgress and placed into a IF End IF statement.

Ty
 
T

Ty

Thanks for the info Nick.

I actually solved it by placing a module level boolean variable into
the Private Sub ExecuteTaskAsync() that is evaluated in the Private
Sub ShowProgress sub. Because I am using a For Next loop I can easily
tell when the task is complete then I simply set the variable and when
it hit the ShowProgress sub and evaluates the variable and sees the
change it runs the code to hide the controls which I moved to the
ShowProgress and placed into a IF End IF statement.

Ty
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top