|
-
Sep 24th, 2008, 12:21 AM
#1
Thread Starter
Hyperactive Member
[RESOLVED] Multiple threads using multiple items in ListBox
I am using multiple threads that are using a list of items on my main form.
When I do the following:
Code Code:
for i = 0 to 4
Dim bk As New BackgroundWork(Me)
Dim t As New Threading.Thread(AddressOf bk.doIt)
t.Start()
next i
Once each thread is done with an item it tells the main form to remove the top most item from the list.
However - All five threads are using the first item in the list before they finally start using unique items from the list.
I even tried delaying the start of each thread to prevent them from all starting at the same time but oddly this still happens.
What do you suggest?
-
Sep 24th, 2008, 12:29 AM
#2
Re: Multiple threads using multiple items in ListBox
You need to synchronise the access to the ListBox so that accessing the next item and then incrementing the next item index is performed atomically. That way you ensure that each thread will not be getting the same item as the thread before it because that thread hasn't had a chance to increment the next item index yet. That might look something like this:
vb.net Code:
Dim item As Object SyncLock syncRoot item = myListBox.Items(itemIndex) itemIndex += 1 End SyncLock
That's a highly simplified example but the Synclock block is the important part, plus the fact that both the item retrieval and index incrementing are both within it. Only one thread at a time can enter that block (as long as syncRoot refers to the same object for each of those threads) so it ensures that once one thread starts getting the next item it will be guaranteed of incrementing the index before another thread tries to get an item.
Note that, to ensure that syncRoot refers to the same object each time, you should use a Shared variable in the BackgroundWork class.
-
Sep 24th, 2008, 12:30 AM
#3
Thread Starter
Hyperactive Member
Re: Multiple threads using multiple items in ListBox
To be more clear:
All five threads use the first item in the list THEN they begin using unique items from the list.
EDIT: Sorry JM, I must have been typing as you were.
-
Sep 24th, 2008, 12:33 AM
#4
Re: Multiple threads using multiple items in ListBox
 Originally Posted by thud
To be more clear:
All five threads use the first item in the list THEN they begin using unique items from the list.
EDIT: Sorry JM, I must have been typing as you were.
Apology accepted.
-
Sep 24th, 2008, 12:48 AM
#5
Thread Starter
Hyperactive Member
Re: Multiple threads using multiple items in ListBox
That worked however now it only works at the speed of running one thread. I assume its because the next thread can't access the list until the first is complete. Is there any way to do it without sacrificing the speed?
Is there any other way to prevent all five threads from using the very first item in the list at start?
Last edited by thud; Sep 24th, 2008 at 12:56 AM.
-
Sep 24th, 2008, 01:13 AM
#6
Re: Multiple threads using multiple items in ListBox
Hold up, hold up! You don't need another way. You already have your solution.
From what you describe I'm guessing that you put the entire code inside the SyncLock block. What did I say the SyncLock block was for?
so that accessing the next item and then incrementing the next item index is performed atomically.
That's all. As I said, only one thread can enter the SyncLock block at a time so obviously you don't want the code that's SUPPOSED to be executed at the same time inside it. You only want the code that gets the item and increments the index inside. Everything else is OUTSIDE and AFTER the SyncLock block. That way as soon as one thread gets its item and then starts using it another thread can enter the SyncLock block to get its item. It will then leave to start using it and the next thread enters, etc.
-
Sep 24th, 2008, 02:11 AM
#7
Thread Starter
Hyperactive Member
Re: Multiple threads using multiple items in ListBox
vb.net Code:
Public Class Form1
Public Sub UpdatelstProcess(ByVal msg As String)
StatusList.items.add msg
'Remove item so next thread doesn't use it and/or so that it isnt used again
ItemList.Items.RemoveAt(0)
End Sub
Private Sub StartBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartBtn.Click
For i As Integer = 0 To 4
Dim bk As New BackgroundWork(Me)
Dim t As New Threading.Thread(AddressOf bk.Vid)
t.Start()
Next
End Sub
End Class
Public Class BackgroundWork
Private mForm As Form1
Private Delegate Sub UpdateListboxHandler(ByVal msg As String)
Sub New(ByVal f As Form1)
Me.mForm = f
End Sub
Public Sub vid()
Dim ThisThreadsItem As String
ThisThreadsItem = mForm.ItemList.Items(0)
'do whatever with ThisThreadsItem
Dim msg As String = ThisThreadsItem & " was processed"
Dim u As New UpdateListBoxHandler(AddressOf Me.mForm.UpdatelstProcess)
Me.mForm.Invoke(u, New Object() {msg})
End Sub
End Class
Last edited by thud; Sep 24th, 2008 at 02:17 AM.
-
Sep 24th, 2008, 02:40 AM
#8
Re: Multiple threads using multiple items in ListBox
That design is obviously flawed. You're just getting the first item every time, assuming that it's the next one to process, yet you don't remove it from the list until you've finished processing it. You need to remove it from the list BEFORE you process it, so that it's not left sitting there for other threads to pick up. getting the first item and removing it from the list should be the contents of the SyncLock block.
-
Sep 24th, 2008, 02:47 AM
#9
Thread Starter
Hyperactive Member
Re: Multiple threads using multiple items in ListBox
v.net Code:
Dim current_email As String
SyncLock ???
current_email = mForm.recip_list.Items(0)
RemoveOne()
End SyncLock
What would the syncRoot be if not BackgroundWork?
-
Sep 24th, 2008, 02:53 AM
#10
Thread Starter
Hyperactive Member
Re: Multiple threads using multiple items in ListBox
-
Sep 24th, 2008, 03:09 AM
#11
Re: [RESOLVED] Multiple threads using multiple items in ListBox
As I said earlier:
Note that, to ensure that syncRoot refers to the same object each time, you should use a Shared variable in the BackgroundWork class.
The object you lock on doesn't have to DO anything. It just has to BE the same object for each SyncLock statement that you want to be "linked". If the same method containing the SyncLock block is going to be executed in multiple BackgroundWork objects then you have to make sure that each BackgroundWork object refers to the same object when locking. How do you make every instance of a type all refer to the same value? Use a Shared variable:
vb Code:
Private Shared syncRoot As New Object
Now one Object instance will be created in the BackgroundWork class regardless of how many instances are created, so every instance can lock on the same object.
-
Sep 24th, 2008, 03:19 AM
#12
Thread Starter
Hyperactive Member
Re: [RESOLVED] Multiple threads using multiple items in ListBox
The object you lock on doesn't have to DO anything.
Yeah, that's what I didn't understand.
Anyway, I learned something new today and this will open many more doors.
Thank you for dealing with my stupidity. I know how painful it is for you.
-
Sep 24th, 2008, 03:29 AM
#13
Re: [RESOLVED] Multiple threads using multiple items in ListBox
Actually, this was one of today's better efforts. There were some painful ones today but this wasn't one of them. Lack of knowledge isn't stupidity and I've never said or implied that it is.
Some people seem incapable of thinking laterally. That frustrates me, yes, but if they can't do it they can't do it. They're not going to make very good programmers in that case though. What really bugs me is lack of application. Those who make no effort to think or look for even part of the solution themselves but just sit back and wait for it to be provided. Whether they consciously decide to do that or just figure it's too hard and they may as well not try doesn't matter. The (assumed) knowledge that you won't succeed in this case is still not a reason to not try. Even if you can't solve your issue you still have the chance to learn something.
So, those are by bugbears and I've not encountered them in this thread, so you get my seal of approval. I will just say one thing, without expecting an answer or reply. I do hope that the first thing you did after I mentioned that you should use a SyncLock block was go to the MSDN Library and read about the SyncLock statement.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|