Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / January 2007

Tip: Looking for answers? Try searching our database.

Control (textbox) update from thread invisible

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
brett.mack@gmail.com - 08 Jan 2007 16:21 GMT
Hello! I'm trying to update a text box from a thread. It works fine
until my thread is created from a seperate class. To illustrate, here's
my form code (the textbox is txtOutput.text) and for the class:

(This all works fine if the "Count" class is declared simply as a
function within form1 - but outside of that the control updates are
invisible!

Imports System.Threading
Delegate Sub SetTextCallback(ByVal [text] As String)
Public Class Form1
   Dim tClass As count
   Dim t As Thread
   Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnStart.Click
       tClass = New count
       t = New Thread(AddressOf tClass.bProcess)
       t.Start()
       While t.IsAlive
           Thread.Sleep(20)
       End While
   End Sub

   Public Sub SetText(ByVal [text] As String)
       ' InvokeRequired required compares the thread ID of the
       ' calling thread to the thread ID of the creating thread.
       ' If these threads are different, it returns true.
       If Me.txtOutput.InvokeRequired Then
           Dim d As New SetTextCallback(AddressOf SetText)
           Me.Invoke(d, New Object() {[text]})
       Else
           Me.txtOutput.Text = [text] & txtOutput.Text
           Me.txtOutput.Refresh()
       End If
   End Sub

   Private Sub btnAbort_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnAbort.Click
       t.Abort()
   End Sub
End Class

And here's the class for the count class:

Public Class count
   Inherits Form1
   Public i As Integer

   Sub New()
       i = 0
   End Sub
   Sub bProcess()
       For i = 1 To 1000
           'If i Mod 25 = 0 Then
           '    SetText(i.ToString & " " & ControlChars.CrLf)
           '    'txtOutput.Text = i.ToString & " " & ControlChars.CrLf
           'Else
           SetText(i.ToString & " ")
           'End If
       Next
   End Sub
End Class
Henning Krause [MVP - Exchange] - 08 Jan 2007 16:56 GMT
Hello,

UI updated are only possible from the thread which created the UI control...

The solution for your problem here is to call the Invoke method from the
Form or Textbox where the form resides and update the Textbox via a
delegate.

Best regards,
Henning Krause

> Hello! I'm trying to update a text box from a thread. It works fine
> until my thread is created from a seperate class. To illustrate, here's
[quoted text clipped - 58 lines]
>    End Sub
> End Class
brett.mack@gmail.com - 08 Jan 2007 17:17 GMT
Yes, but how do I do that?

> Hello,
>
[quoted text clipped - 69 lines]
> >    End Sub
> > End Class
Henning Krause [MVP - Exchange] - 08 Jan 2007 18:14 GMT
Hell,

looking at your code...

>> >        While t.IsAlive
>> >            Thread.Sleep(20)
>> >        End While

This effectively block your Message queue on your window from being
processed....

And I don't understand why you do this...

Best regards,
Henning Krause

why do you
> Yes, but how do I do that?
>
[quoted text clipped - 72 lines]
>> >    End Sub
>> > End Class
brett.mack@gmail.com - 09 Jan 2007 13:49 GMT
I was assuming that if I didn't do this, the main thread would just
suck all of the processor iterating through the while loop; I guess now
that isn't correct? Sorry, I've been teaching myself on the fly, no
formal programming education (I'm sure it shows)!
The below code works.

Question: On the main form code "SetText" routine, should I uncomment
the Monitor.Enter(me) & Monitor.Exit(me) when I have more than one
background thread running at the same time, updating the textbox?

What I've done so far is this. Main form code follows:
Imports System.Threading
Public Delegate Sub SetTextCallback(ByVal [text] As String)

Public Class Form1
   Dim tClass As count
   Dim t As Thread
   Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnStart.Click
       btnStart.Enabled = False
       tClass = New count
       t = New Thread(AddressOf tClass.bProcess)
       t.Start()
       btnStart.Enabled = True
   End Sub
   Public Sub SetText(ByVal [text] As String)
       ' InvokeRequired required compares the thread ID of the
       ' calling thread to the thread ID of the creating thread.
       ' If these threads are different, it returns true.
       'Monitor.Enter(Me)
       If Me.txtOutput.InvokeRequired Then
           Dim d As New SetTextCallback(AddressOf SetText)
           Me.Invoke(d, New Object() {[text]})
       Else
       Me.txtOutput.Text = [text] & txtOutput.Text
           Me.txtOutput.Refresh()
       End If
       'Monitor.Exit(Me)
   End Sub
   Private Sub btnAbort_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnAbort.Click
       t.Abort()
   End Sub

End Class

And in the "Count" class code, I've put this:

Imports system.threading

Public Class count
   Public i As Integer
   Dim f1 As Form1
   Dim st As SetTextCallback
   Sub New()
       i = 0
       st = New SetTextCallback(AddressOf Form1.SetText)
   End Sub
   Sub bProcess()
       For i = 1 To 1000
           st(i.ToString & " ")
           Thread.Sleep(10)
       Next
   End Sub
End Class

> Hell,
>
[quoted text clipped - 89 lines]
> >> >    End Sub
> >> > End Class
Henning Krause [MVP - Exchange] - 09 Jan 2007 14:39 GMT
Hello,

I would assume that setting a text value is not a thread safe operaiton, so
using a Monitor here is ok. But you should use the SyncLock keyword in
Visual Basic, as it will wrap the Monitor.Exit in a finally block.

Best regards,
Henning Krause

>I was assuming that if I didn't do this, the main thread would just
> suck all of the processor iterating through the while loop; I guess now
[quoted text clipped - 158 lines]
>> >> >    End Sub
>> >> > End Class
Lasse Vågsæther Karlsen - 10 Jan 2007 12:51 GMT
> I was assuming that if I didn't do this, the main thread would just
> suck all of the processor iterating through the while loop; I guess now
[quoted text clipped - 5 lines]
> the Monitor.Enter(me) & Monitor.Exit(me) when I have more than one
> background thread running at the same time, updating the textbox?
<snip>
>>>>>    Public Sub SetText(ByVal [text] As String)
>>>>>        ' InvokeRequired required compares the thread ID of the
[quoted text clipped - 8 lines]
>>>>>        End If
>>>>>    End Sub
<snip>

You do not need the monitor for this method, the way it is above is
fine. Messages to the main thread are processed one at a time.

Signature

Lasse Vågsæther Karlsen
mailto:lasse@vkarlsen.no


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.