|
-
May 28th, 2010, 10:35 AM
#1
Thread Starter
Lively Member
How to get a variable/value out of a thread?
I want to write some code to do some processing. This seems best done in a thread. But I also want some UI and general controlling passed to and from it. eg: Adding lines to a text box for general UI updating while it's running.
Now, let's assume I might have multiple threads running, so each thread can call my UpdateUI subroutine. But the problem is, at the moment my code is using a public variable UI_Msg to pass values back from each thread to the UpdateUI subroutine. This hits me as dangerous as different threads may overwrite UI_Msg at the same time.
Instead I tryied to attach a class to each thread, so each thread has its own UI_Msg property/value. When I then get to UpdateUI, I want to pluck this value out of that thread, so there's no risk of different threads overwriting each others msgs to UpdateUI.
I've attached my code example.
So all I want to do is in UpdateUI, be able to look at UI_msg from the class for the thread calling UpdateUI. eg: Obtain thread.UI_msg for example...
Code:
Imports System.Threading
Public Class MainForm
Public UI_msg As String
' Used to track which thread called the UI Update function.
Private callingThread As Integer
' The Delegate that is invoked by the control on the form that needs to be updated.
Delegate Sub UIDelegate()
Private Sub UpdateUI()
' If InvokeRequired is true then the call is being made on a thread other
' than the UI thread.
If Label1.InvokeRequired Then
' Call UpdateUI by invoking a delegate with the UI control
callingThread = System.Threading.Thread.CurrentThread.ManagedThreadId()
Dim newDelegate As New UIDelegate(AddressOf UpdateUI)
Label1.Invoke(newDelegate)
Else
Label1.AppendText(Text + "Thread " + callingThread.ToString() + ":" + UI_msg + vbCrLf)
' ** How can I get the UI_MSG from the thread class? **
UI_msg = ""
Label1.ScrollToCaret()
End If
End Sub
Private Sub StartJob_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartJob.Click
UI_msg = "Starting a new thread"
UpdateUI()
Dim JobThread As New Thread(AddressOf RunJob)
JobThread.Start()
End Sub
Class JobObjClass
Public JobCanceled As Boolean
Public UI_Msg As String
End Class
Sub RunJob()
Dim StateObj As New JobObjClass()
StateObj.JobCanceled = False
Dim ctr As Integer
ctr = 0
While (ctr < 5 And abort = False)
System.Threading.Thread.Sleep(1000)
ctr = ctr + 1
UI_msg = "Count " & ctr.ToString()
StateObj.UI_Msg = "Count " & ctr.ToString() ' ** Want to use this instead of previous line!
UpdateUI()
End While
StateObj.JobCanceled = True
UI_msg = "Ending thread"
UpdateUI()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
abort = True
End Sub
End Class
I hope this makes sense... I'm only a week or so into Visual Basic.
Last edited by NeilF; May 28th, 2010 at 10:51 AM.
-
May 28th, 2010, 11:23 AM
#2
Thread Starter
Lively Member
Re: How to get a variable/value out of a thread?
I think I've done it 
Code:
Imports System.Threading
Public Class MainForm
Public jobs_running As Integer
Public abort As Boolean
' Used to track which thread called the UI Update function.
Private callingThread As Integer
' The Delegate that is invoked by the control on the form that needs to be updated.
Delegate Sub UIDelegate(ByVal StatusMessage As String)
Sub UpdateUI(ByVal Message As String)
' If InvokeRequired is true then the call is being made on a thread other
' than the UI thread.
If Label1.InvokeRequired Then
' Call UpdateUI by invoking a delegate with the UI control
callingThread = System.Threading.Thread.CurrentThread.ManagedThreadId()
Dim newDelegate As New UIDelegate(AddressOf UpdateUI)
Dim args() As Object = {Message}
Label1.Invoke(newDelegate, args)
Else
Label1.AppendText(Text + "Thread " + callingThread.ToString() + ":" + Message + vbCrLf)
' ** How can I get the UI_MSG from the thread class? **
Label1.ScrollToCaret()
Label2.Text = jobs_running.ToString()
End If
End Sub
Private Sub StartJob_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartJob.Click
jobs_running = jobs_running + 1
UpdateUI("Starting a New Thread")
Dim JobThread As New Thread(AddressOf RunJob)
JobThread.Start()
End Sub
Sub RunJob()
Dim ctr As Integer
ctr = 0
While (ctr < 5 And abort = False)
System.Threading.Thread.Sleep(1000)
ctr = ctr + 1
UpdateUI("Count " & ctr.ToString())
End While
jobs_running = jobs_running - 1
UpdateUI("Ending Thread")
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
abort = True
End Sub
Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
End Class
-
May 28th, 2010, 12:21 PM
#3
Fanatic Member
Re: How to get a variable/value out of a thread?
I normally use a backgroundworker for threading...
Backgroundworkers can NOT update a control in the dowork function, but CAN in the report/completed functions.
So it, requires a bit of ingenuity to get it to all function.
i am glad you think you figured it out, as i didnt really look at your code. Its always nice to see people figure things out on their own, as thats how learning works
-
May 28th, 2010, 01:34 PM
#4
Thread Starter
Lively Member
Re: How to get a variable/value out of a thread?
 Originally Posted by TCarter
I normally use a backgroundworker for threading...
Backgroundworkers can NOT update a control in the dowork function, but CAN in the report/completed functions.
So it, requires a bit of ingenuity to get it to all function.
i am glad you think you figured it out, as i didnt really look at your code. Its always nice to see people figure things out on their own, as thats how learning works 
I sort of get what it's doing, but I've patched it togethor from examples and guess work, so I don't pretend to fully understand it... Especially the Delegate stuff 
Just wish I had an answer to this problem - http://www.vbforums.com/showthread.php?t=616099#18
-
May 28th, 2010, 01:54 PM
#5
Re: How to get a variable/value out of a thread?
A delegate is a pointer to a function. Think of it as an address on an envelope. Or a telephone number... you can't talk to you friend because he's on a different thread from you (his house vs your house) ... so you dial him up using a delegate (the phone) .. the phone acts like a proxy between your thread and your friend's thread, allowing communication (via phone wired or even cell phone towers).
What you have there should work... it looks like you've set it up correctly.
the InvokeRequired is like you yelling "Hey Buddy!" in your house... if he's not there (since he's at home), you have to go through your delegate (the phone) ... where it then gets routed around until it gets to your friend and he gets the message.
it's a messy example, but I think it illustrates the concepts at least.
-tg
-
May 28th, 2010, 04:52 PM
#6
Re: How to get a variable/value out of a thread?
Code:
Dim go As Long = 0
Dim ct As Long = 0
Dim lock As New Object
Dim running As Long
Const _toRun As Integer = 20 'try different numbers
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Button2.Enabled = False
Label1.Text = DateTime.Now.ToLongTimeString 'set up
Threading.Interlocked.Exchange(go, 0L)
Threading.Interlocked.Exchange(ct, 0L)
Threading.Interlocked.Exchange(running, 0)
For x As Integer = 1 To _toRun 'start some threads
Dim t As New Threading.Thread(AddressOf foo)
t.Start()
Threading.Thread.Sleep(10) 'give each one a chance to start
Next
Do 'wait for all to start
Threading.Thread.Sleep(10)
Loop While _toRun <> Threading.Interlocked.Read(running)
Button3.Enabled = True
Threading.Interlocked.Exchange(go, 1L) 'GO!
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
Threading.Interlocked.Exchange(go, 0L) 'STOP
Button3.Enabled = False
aTimer.Interval = 100
aTimer.Start()
End Sub
Dim WithEvents aTimer As New Timer()
Private Sub _Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles aTimer.Tick
If Threading.Interlocked.Read(running) > 0 Then Exit Sub
aTimer.Stop()
Label1.Text = DateTime.Now.ToLongTimeString
Button2.Enabled = True
End Sub
Private Sub foo()
Dim myID As Long = Threading.Interlocked.Increment(ct) 'get myID
Threading.Interlocked.Increment(running)
'wait for all threads to be started
Do While Threading.Interlocked.Read(go) = 0L
Threading.Thread.Sleep(10) 'sleep if not
Loop
Do
Threading.Monitor.Enter(lock) 'lock
updUI(myID) 'update the UI passing in myID <<< Update UI
Threading.Monitor.Exit(lock) 'unlock
Threading.Thread.Sleep(100) 'comment this out and see the difference
Loop While Threading.Interlocked.Read(go) = 1L
Threading.Interlocked.Decrement(running)
End Sub
Delegate Sub Stub(ByVal aCount As Long)
Public myDelegate As Stub
Private Sub updUI(ByVal theCount As Long)
If Label1.InvokeRequired Then 'on UI thread
myDelegate = New Stub(AddressOf updUI) 'no
Label1.Invoke(myDelegate, theCount) 'this will run on the UI
Exit Sub
End If
Dim s As String = Space(CInt(theCount)) & CLng(theCount).ToString
Label1.Text = s
Label1.Refresh()
End Sub
-
May 29th, 2010, 03:07 AM
#7
Thread Starter
Lively Member
Re: How to get a variable/value out of a thread?
 Originally Posted by dbasnett
Code:
Dim go As Long = 0
Dim ct As Long = 0
Dim lock As New Object
Dim running As Long
Const _toRun As Integer = 20 'try different numbers
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Button2.Enabled = False
Label1.Text = DateTime.Now.ToLongTimeString 'set up
Threading.Interlocked.Exchange(go, 0L)
Threading.Interlocked.Exchange(ct, 0L)
Threading.Interlocked.Exchange(running, 0)
For x As Integer = 1 To _toRun 'start some threads
Dim t As New Threading.Thread(AddressOf foo)
t.Start()
Threading.Thread.Sleep(10) 'give each one a chance to start
Next
Do 'wait for all to start
Threading.Thread.Sleep(10)
Loop While _toRun <> Threading.Interlocked.Read(running)
Button3.Enabled = True
Threading.Interlocked.Exchange(go, 1L) 'GO!
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
Threading.Interlocked.Exchange(go, 0L) 'STOP
Button3.Enabled = False
aTimer.Interval = 100
aTimer.Start()
End Sub
Dim WithEvents aTimer As New Timer()
Private Sub _Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles aTimer.Tick
If Threading.Interlocked.Read(running) > 0 Then Exit Sub
aTimer.Stop()
Label1.Text = DateTime.Now.ToLongTimeString
Button2.Enabled = True
End Sub
Private Sub foo()
Dim myID As Long = Threading.Interlocked.Increment(ct) 'get myID
Threading.Interlocked.Increment(running)
'wait for all threads to be started
Do While Threading.Interlocked.Read(go) = 0L
Threading.Thread.Sleep(10) 'sleep if not
Loop
Do
Threading.Monitor.Enter(lock) 'lock
updUI(myID) 'update the UI passing in myID <<< Update UI
Threading.Monitor.Exit(lock) 'unlock
Threading.Thread.Sleep(100) 'comment this out and see the difference
Loop While Threading.Interlocked.Read(go) = 1L
Threading.Interlocked.Decrement(running)
End Sub
Delegate Sub Stub(ByVal aCount As Long)
Public myDelegate As Stub
Private Sub updUI(ByVal theCount As Long)
If Label1.InvokeRequired Then 'on UI thread
myDelegate = New Stub(AddressOf updUI) 'no
Label1.Invoke(myDelegate, theCount) 'this will run on the UI
Exit Sub
End If
Dim s As String = Space(CInt(theCount)) & CLng(theCount).ToString
Label1.Text = s
Label1.Refresh()
End Sub
Are you able to explain:-
Threading.Interlocked.Read
Threading.Monitor.Enter
Threading.Monitor.Exit
With my previous example, all my threads would run in parallel. How does the above example work? It seems at the very least to lock around the UI updating?
-
May 29th, 2010, 05:52 AM
#8
Re: How to get a variable/value out of a thread?
 Originally Posted by NeilF
Are you able to explain:-
Threading.Interlocked.Read
Threading.Monitor.Enter
Threading.Monitor.Exit
With my previous example, all my threads would run in parallel. How does the above example work? It seems at the very least to lock around the UI updating?
I can, can you Threading Link
"It seems at the very least to lock around the UI updating?" Wasn't your post about having multiple threads updating the UI? That is what it does.
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
|