Question Multi-threading in GUI environment

siddhc

New member
Joined
Aug 7, 2010
Messages
2
Programming Experience
Beginner
Hi,

I made a simple Form1, with Text.Box1 (starting value=1) and Text.Box2 (starting value = 100000), as shown below :
Form1.GIF

I wanted that, when the Form loads,value of Text.Box1 keeps on increasing by 2 and value of Text.Box2 keeps on decreasing by 3. I wanted to achieve this by multi-threading.

Following is the code I wrote, which definitely has some problem with it.
*************************************************************

Imports System.Threading.Thread

Public Delegate Sub funcHolder(ByVal diff1234 As Integer)

Public Class Form1
Dim i As Integer
Dim j As Integer
'-------------------------------------------------------------
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim upd12Holder As funcHolder
Dim upd34Holder As funcHolder
upd12Holder = AddressOf upd12
upd34Holder = AddressOf upd34
Dim t12 As New System.Threading.Thread(AddressOf upd12)
t12.Start(2)
Dim t34 As New System.Threading.Thread(AddressOf upd12)
t12.Start(3)
End Sub
'-------------------------------------------------------------
Public Sub upd12(ByVal diff12 As Integer)
While (1)
TextBox1.Text = TextBox1.Text + diff12
For i = 1 To 10000 'delay loop
Next i
End While
End Sub
'-------------------------------------------------------------
Public Sub upd34(ByVal diff34 As Integer)
While (1)
TextBox2.Text = TextBox2.Text - diff34
For j = 1 To 10000 'delay loop
Next j
End While
End Sub
'-------------------------------------------------------------
End Class

*************************************************************

It would be very helpful if you could help me identify and correct the problem.

Thank you all.
 

Satal Keto

Well-known member
Joined
May 15, 2006
Messages
86
Programming Experience
5-10

rlange

New member
Joined
Aug 17, 2010
Messages
3
Programming Experience
Beginner
you should not access windows controls on any other thread but the gui thread. You can but it will create major havoc, and your program will only work sometimes and lockup constantly. If a control is doing something like painting, updating, etc. and you attemp to access it via another thread, it will cause your program to lockup. You can use threading.thread.sleep instead of the loops for delay, as the loop time will be different on different computers. You can use me.invokerequired and me.invoke to pass control back to the gui thread to make the update to the textbox. I would probably make variable to hold the numbers, do all the math in the threads and marshall the calls that update the textbox back to the gui thread. I would also recommend setting thread.isbackground=true as it will cause the threads to terminate when your program closes. If not and the threads are infinite loop, it will cause the program to stay open even after the main gui is closed and will you have to endtask to close it. I can provide some examples if you have not found a solution to this problem
 
Last edited:

siddhc

New member
Joined
Aug 7, 2010
Messages
2
Programming Experience
Beginner
Thank you all for your valuable inputs. I learnt some new things from each post.

However, I have not been able to solve it on my own.

'rlange' please send me a simple example so that I can unserstand the process. Thanks a lot.
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,295
Location
Sydney, Australia
Programming Experience
10+
Thank you all for your valuable inputs. I learnt some new things from each post.

However, I have not been able to solve it on my own.

'rlange' please send me a simple example so that I can unserstand the process. Thanks a lot.
If you've read my link then you've already got a simple example and you've even got step-by-step instructions on how to do do it for yourself. If you don't understand that then how is another example going to help? How about you show us what you did, step by step, to follow the instructions I provided? Once we see what you did then we can see what you did wrong. Then we can help you fix it. When there are already who knows how many examples already on the web and people say "give me an example", what they're really saying is "write my code for me".
 

rlange

New member
Joined
Aug 17, 2010
Messages
3
Programming Experience
Beginner
Thank you all for your valuable inputs. I learnt some new things from each post.

However, I have not been able to solve it on my own.

'rlange' please send me a simple example so that I can unserstand the process. Thanks a lot.

Drop this code into a form. Create 2 buttons named butStartThreads butStopThreads and 2 textboxes named txtThread1 txtThread2. Let me know if you have any questions.

Code:
    'thread 1 object
    Public Thread1 As Threading.Thread
    'variable to hold value for thread1
    Public Thread1Var As Integer = 1

    'thread 2 object
    Public Thread2 As Threading.Thread
    'variable to hold value for thread2
    Public Thread2Var As Integer = 100000

    'delegate sub for marshalling control to gui thread. takes value and textbox to write it to
    Public Delegate Sub WriteValueDelegate(ByVal v As Integer, ByVal t As TextBox)

    Public Sub Thread1Loop()
        While True
            'increasing thread1var
            Thread1Var = Thread1Var + 2
            'calling sub to write new value on thread1
            WriteValue(Thread1Var, txtThread1)
            'pausing current thread 1 (not gui thread)
            Threading.Thread.Sleep(100)
        End While
    End Sub

    Public Sub Thread2Loop()
        While True
            'decreasing thread2 var
            Thread2Var = Thread2Var - 3
            'calling sub to write new value on thread2
            WriteValue(Thread2Var, txtThread2)
            'pausing current thread 2 (not gui thread)
            Threading.Thread.Sleep(100)
        End While
    End Sub

    Public Sub WriteValue(ByVal val As Integer, ByVal txt As TextBox)
        'me.invokerequired will be true if this sub is called from non gui thread. (ie call from one of the threadloops)
        If Me.InvokeRequired = True Then
            'if called from non gui thread, we use me.invoke to pass call to the gui thread.
            'invoke takes a delegate sub which we create and point to this same method
            'we pass all parameters recv in an object array
            'this essentially calls writevalue again (2nd time), passing arguements along, but calls on the gui thread.
            Me.Invoke(New WriteValueDelegate(AddressOf WriteValue), New Object() {val, txt})
        Else
            'this will be called when the above line of code invokes the delegate. Essentially we are on the gui thread at this point
            txt.Text = val
        End If
    End Sub

    Private Sub butStartThreads_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butStartThreads.Click
        'starting thread
        Thread1 = New Threading.Thread(AddressOf Thread1Loop)
        'isbackground ensures thread will stop with program closes
        Thread1.IsBackground = True
        Thread1.Start()

        Thread2 = New Threading.Thread(AddressOf Thread2Loop)
        'isbackground ensures thread will stop with program closes, otherwi
        Thread2.IsBackground = True
        Thread2.Start()

    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        'be sure to abort threads before form closes since threads access form
        butStopThreads_Click(Nothing, Nothing)
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'start threads when form loads
        butStartThreads_Click(Nothing, Nothing)
    End Sub

    Private Sub butStopThreads_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butStopThreads.Click
        'abort threads
        Thread1.Abort()
        Thread2.Abort()
    End Sub
 
Top Bottom