|
-
Dec 28th, 2008, 08:16 PM
#1
Passing Data to a Thread Entry Method
C# version here.
Originally there was no way to pass data directly to a method that you were using as the entry point for a thread. You had to assign your data to one or more member variables and then retrieve it again in the new thread.
vb.net Code:
Private data As Integer Private Sub InitiateThread() Me.data = 100 Dim t As New Thread(AddressOf DoWork) t.Start() End Sub Private Sub DoWork() Dim data As Integer = Me.data 'Use data here. End Sub
Many developers would create classes specifically for the new thread that incorporated the data, which was assigned to properties, and the thread entry point.
vb.net Code:
Private Class Worker Private _data As Integer Public WriteOnly Property Data() As Integer Set(ByVal value As Integer) Me._data = value End Set End Property Public Sub DoWork() Dim data As Integer = Me._data 'Use data here. End Sub End Class Private Sub InitiateThread() Dim w As New Worker w.Data = 100 Dim t As New Thread(AddressOf w.DoWork) t.Start() End Sub
With .NET 2.0 came the ParameterizedThreadStart delegate and the ability to pass a single object to the entry method via the Thread.Start method.
vb.net Code:
Private Sub InitiateThread() Dim t As New Thread(AddressOf DoWork) t.Start(100) End Sub Private Sub DoWork(ByVal obj As Object) Dim data As Integer = CInt(obj) 'Use data here. End Sub
Now, with VB 2008, we have a new way, thanks to Lambda Expressions. This is easier and neater than the old ways and overcomes the weak typing required by the ParameterizedThreadStart delegate. With this new approach you can write a function that takes as many arguments as you like of whatever type you like. You then create a ThreadStart delegate using a Lambda Expression that calls this function, e.g.
vb.net Code:
Private Sub InitiateThread() Dim t As New Thread(DirectCast(Function() DoWork(100), ThreadStart)) t.Start() End Sub Private Function DoWork(ByVal data As Integer) As Object 'Use data here. Return Nothing End Function
The only real drawback with this approach is that your work method MUST be a function, even though the return value cannot be used anywhere. When VB 2010 arrives that will no longer be the case because Lambda Expressions will be able to be Subs as well as Functions.
I have to admit that I don't really understand how a cast from a Lambda Expression that's a function to type ThreadStart, which has no return type, is legal but it seems to work so I'm happy to use it.
Last edited by jmcilhinney; Dec 28th, 2008 at 11:16 PM.
-
Nov 26th, 2010, 10:51 PM
#2
Re: Passing Data to a Thread Entry Method
VB 2010 has added support for action lambdas to the existing value lambdas, i.e. you can now create a lambda expression using the Sub keyword as well as the Function keyword. As such, the issue with the last code snippet in post #1 is removed in VB 2010:
vb.net Code:
Private Sub InitiateThread() Dim t As New Thread(DirectCast(Sub() DoWork(100), ThreadStart)) t.Start() End Sub Private Sub DoWork(ByVal data As Integer) 'Use data here. End Sub
-
Jun 8th, 2011, 02:39 PM
#3
Fanatic Member
Re: Passing Data to a Thread Entry Method
hello thanks jmcilhinney for this brief,
in the class approach of this threading, will this method avoid data overwriting (race condition) since the same DoWork will be used by multiple threads
since you say
vb Code:
Private Sub InitiateThread()
Dim w As New Worker
w.Data = 100
Dim t As New Thread(AddressOf w.DoWork)
t.Start()
End Sub
-
Jun 8th, 2011, 06:45 PM
#4
Re: Passing Data to a Thread Entry Method
 Originally Posted by coolcurrent4u
hello thanks jmcilhinney for this brief,
in the class approach of this threading, will this method avoid data overwriting (race condition) since the same DoWork will be used by multiple threads
since you say
vb Code:
Private Sub InitiateThread()
Dim w As New Worker
w.Data = 100
Dim t As New Thread(AddressOf w.DoWork)
t.Start()
End Sub
But it's not the same DoWork method. You're creating a new Worker object each time and each of those objects has its own Data property and DoWork method. It would only be if you used the same Worker object each time or Worker was a module or a class with Shared members that you would experience interference between threads.
-
Jun 9th, 2011, 05:36 AM
#5
Fanatic Member
Re: Passing Data to a Thread Entry Method
Hello John
Am getting race condition with this implementation. in the listview, one item is usually listed more than once, which is not suppose to be so. The my code
I wanted to use the class implementation, but how do i get the clas to return values so i can display it in list view just like thsi one
vb Code:
Sub Button1Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnStart.Click
ListItemsToProcess.AddRange(TextBox1.Lines)
count = 0
StartProcess()
End Sub
Private Sub StartProcess()
Me.btnStart.Enabled = False
' start the first five threads
For i = 0 To intMaxThreadCount - 1
If intNextItemIndex < ListItemsToProcess.Count Then
Threading.Thread.Sleep(100)
StartNextItem(i)
End If
Next
' update running threads
End Sub
Private Sub StartNextItem(ByVal index As Integer)
If index < ListItemsToProcess.Count Then
' start parsing thread
Dim t As New Thread(AddressOf DoWork)
t.Name = "Thread " & index
t.Start(index)
intNextItemIndex += 1
End If
End Sub
Private Sub DoWork(ByVal data As Object)
Dim index As Integer = CInt(data)
Dim sTemp As String = Nothing
Dim objLock As Object = New Object()
Dim t As Double = 0
myWatch = New Stopwatch
Try
' Proces item
myWatch.Start()
SyncLock (objLock)
sTemp = ProcessData(ListItemsToProcess(index).ToString)
'sTemp = CountTo().ToString
End SyncLock
myWatch.Stop()
t = myWatch.ElapsedMilliseconds / 1000
Catch ex As Exception
' catch error
sTemp = ex.Message
Debug.Print(sTemp)
End Try
Debug.Print(index.ToString)
'AddItem(index, sTemp)
AddItem(index, t.ToString)
StartNextItem(intNextItemIndex)
End Sub
Public Delegate Sub AddItemDelegate(ByVal index As Integer, ByVal item As String)
Public Sub AddItem(ByVal index As Integer, ByVal item As String)
Dim objLock As Object = New Object()
If Me.InvokeRequired Then
Me.Invoke(New AddItemDelegate(AddressOf AddItem), index, item)
Else
Dim lvItem As New ListViewItem
With lvItem
.Text = index.ToString
.SubItems.Add(ListItemsToProcess(index).ToString)
If item.Length < 51 Then
.SubItems.Add(item.ToString)
Else
.SubItems.Add(item.Length.ToString)
End If
End With
count = Interlocked.Increment(count)
tspbStatus.Value = CInt((count / ListItemsToProcess.Count) * 100)
SyncLock (objLock)
listView1.Items.Add(lvItem)
End SyncLock
End If
End Sub
Last edited by coolcurrent4u; Jun 9th, 2011 at 05:53 AM.
-
Sep 2nd, 2011, 11:57 AM
#6
Re: Passing Data to a Thread Entry Method
Hi john, would it be rude to ask a quick question on thread termination here? I dont really feel it needs it's own thread.
-
Sep 2nd, 2011, 07:38 PM
#7
Re: Passing Data to a Thread Entry Method
 Originally Posted by ident
Hi john, would it be rude to ask a quick question on thread termination here? I dont really feel it needs it's own thread.
The thread title says "Passing Data to a Thread Entry Method". Is your question about that? It would appear not, so it doesn;t belong in this thread.
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
|