[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

VB.NET Thread issue

Posted on 2011-03-12
19
Medium Priority
?
523 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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 1000 total points
ID: 35116397
0
 
LVL 86

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 1000 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 86

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
 
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 86

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 86

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 86

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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

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…
Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Suggested Courses

656 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