Solved

VB.NET Thread issue

Posted on 2011-03-12
19
475 Views
Last Modified: 2012-05-11
When a thread I started finishes, I raises an event back to the main process that the thread has completed.  One of the things I want to do in this call back is add an entry to a list box on the main form, but when the event happens I get this error:

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

How can I add an entry to this list box from the finishing thread?


0
Comment
Question by:onemorecoke
  • 6
  • 5
  • 5
  • +1
19 Comments
 
LVL 17

Expert Comment

by:nepaluz
ID: 35116179
Have you implemented your custom threading or utilised the "out of the box" threading of background worker? I'd use the latter and simply add the call to UI in the process changed event.
0
 
LVL 3

Author Comment

by:onemorecoke
ID: 35116211
Here is the code involved:

=========================
Up top in the main form:

Dim t As clsThreadWritebackBatch
Dim ThreadBatch As System.Threading.Thread


=========================
The button click that creates the thread:

If ThreadBatch Is Nothing Then
                Dim t As New clsThreadWritebackBatch
                Dim ThreadBatch As New System.Threading.Thread(AddressOf t.ProcessBatch)
                AddHandler t.FinishedBatch, AddressOf FinishedBatchEventHandler
                ThreadBatch.Priority = System.Threading.ThreadPriority.BelowNormal
                ThreadBatch.Start()
End If

=========================
The callback function

Public Sub FinishedBatchEventHandler(ByVal ItemCount As Long)
...
lbStatus.Items.Add(FormatDateTime(Now, DateFormat.GeneralDate) & " - Finished")
...
end sub


0
 
LVL 12

Expert Comment

by:Mohamed Abowarda
ID: 35116312
The exception is occurring because you are calling the method FinishedBatchEventHandler() from another thread other than the main one that it was created on.

You need to use delegate to call FinishedBatchEventHandler from the main thread.
0
 
LVL 17

Expert Comment

by:nepaluz
ID: 35116368
It may be worth your while to run your rule over the following walk-through in implementing the backgroundworker as a class (out of the box threading).

http://msdn.microsoft.com/en-us/library/ywkkz4s1.aspx
0
 
LVL 12

Accepted Solution

by:
Mohamed Abowarda earned 250 total points
ID: 35116397
0
 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 250 total points
ID: 35116464
I agree that the BackgroundWorker() is much easier.

Here's how to do it the manual way though:
Public Delegate Sub FinishedDelegate(ByVal ItemCount As Long)

Public Sub FinishedBatchEventHandler(ByVal ItemCount As Long)
    If Me.InvokeRequired Then
        Me.Invoke(New FinishedDelegate(AddressOf FinishedBatchEventHandler), New Object() {ItemCount})
    Else
        ' *** it's safe to update any GUI elements in this 'Else' block ***
        ...
        lbStatus.Items.Add(FormatDateTime(Now, DateFormat.GeneralDate) & " - Finished")
        ...
    End If
End Sub

Open in new window

0
 
LVL 3

Author Comment

by:onemorecoke
ID: 35117511
When you say "manual way", does that mean that the backgroundworker component is doing the same thing I am doing manually or is it a completely different thing?  I am used to in-process and out-of-process terminology.  Is what I am doing out-of-process?

Thanks
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35117532
Using the BackgroundWorker() control you don't need to use Invoke()/Delegates since the ProgressChanged() and RunWorkerCompleted() events have already been marshaled to the main UI thread for you.  So when those events are received you can simply directly update your GUI without worrying about it.

...so "under the hood" the BackgroundWorker() control is doing this kind of thing for you.  There are situations where knowing how to do it manually are beneficial as well.
0
 
LVL 3

Author Comment

by:onemorecoke
ID: 35117549
Thanks Idle_Mind!  Would you be able to show me how I could accomplish this with the BackgroundWorker() control?
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 12

Expert Comment

by:Mohamed Abowarda
ID: 35117579
"Cross-thread operation not valid" exception only occurs when you try to make changes on controls from another thread other than the one that it was created on.

After you add the BackgroundWorker to your form, call BackgroundWorker1.RunWorkerAsync() to start.

The BackgroundWorker support three main events:
1. DoWork:
It occur after you call RunWorkerAsync() method and it execute the code on another thread other than the main one.

2. ProgressChanged:
This event raise whenever you call ReportProgress() method and it execute the code on the main thread (you can make any change on controls using this event)

3. RunWorkerCompleted:
It occur after the whole process on DoWork is completed.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35117588
Are you creating just ONE instance of clsThreadWritebackBatch() at a time and waiting for the results?
...or do you need lots of these things running at the same time?
0
 
LVL 3

Author Comment

by:onemorecoke
ID: 35117739
For this specific process, yes just one.  My next situation though is launching multiple threads with the same class.
0
 
LVL 17

Expert Comment

by:nepaluz
ID: 35117917
I do not know whether you dislike my advice, however, the best by far example would be the walk-through that I gave you earlier.

The walk-through shows you how to create a class implementing the background worker. It is simple and concise and its up to you how far you want to take it from there. I will give you the link again

http://msdn.microsoft.com/en-us/library/ywkkz4s1.aspx
0
 
LVL 12

Expert Comment

by:Mohamed Abowarda
ID: 35117927
@onemorecoke: Have you tried to use BackgroundWorker as I posted above?

It will solve your issue.
0
 
LVL 3

Author Comment

by:onemorecoke
ID: 35118015
Medo3337, I am experimenting to see what works best for my situation, thanks for checking in.
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35118398
The link by nepaluz does give a good example.

Basically INSIDE your clsThreadWritebackBatch() class you would encapsulate a BackgroundWorker() control and in the DoWork() handler you execute your code that is now in your manual thread.  You pass the result to the RunWorkerCompleted() event and from there you can raise you classes FinishedBatch() event.
0
 
LVL 3

Author Comment

by:onemorecoke
ID: 35119415
Ok, thanks.  Last question, just trying to decide on using a backgroundworker component or manual method.  Can you set thread priority using the backgroundworker component or is that something that I will have to use the manual method for?  Thanks everyone.

0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 35119441
Don't think you can set the priority on the backgroundworker...
0
 
LVL 12

Expert Comment

by:Mohamed Abowarda
ID: 35119516
If you want to set the thread priority you will have to use Threading class:
http://www.java2s.com/Code/VB/Thread/ThreadpriorityHighestandnormal.htm
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This tutorial demonstrates one way to create an application that runs without any Forms but still has a GUI presence via an Icon in the System Tray. The magic lies in Inheriting from the ApplicationContext Class and passing that to Application.Ru…
Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…

895 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now