Hi,
I wanted to have a TextBox which shows a certain string character by character, like somebody is typing the text for you. I have done it and it works!
But the problem is about its 'performance' after the Textbox becomes large. The text becomes blinking badly while appending text when the FontSize is more than 26pt and/or when the text becomes heavy. Here's the way I did it:
Dim Counter as integer = 0
Dim String1 as string = "This is typed character-by-character!"
I added a timer in my form,
and put these lines into the timer_tick sub:
If Not Counter > String1.Length - 1 Then
TextBox1.AppendText(String1(Counter))
Counter += 1
Else
Timer1.Enabled = False
Counter = 0
End If
I tried using a Label instead of a TextBox, and it never blinks at all!
But since Labels have not the editing ability, I have to use a TextBox.
Do you have a solution for the blinking of this TextBox?
I found something about ThreadSafe Appending, but as a newbie, I don't know what's that all about. Please Help!
[EDIT -- in response to solution by SA]
Hello SA!
Thanks for your response. I read the
Threading issue from the microsoft page. I used it in my project and it brought me an error that I fixed according to this
ThreadSafe msdn page.
Now I have removed the timer and used a Thread instead.
But the result doesn't seem to be much better than previous non-threading way.
Here is the new code:
Imports System.Threading
Public Class Form1
Delegate Sub AppTextCallback(ByVal [text] As String)
Dim Thread1 As Thread
Dim Counter As Short
Dim String1 As String = "This string is typed character by character. It is just fine in the beginning of the text, but as the string becomes longer and longer, then, the blinking issues appear to the viewer! This string is typed character by character. It is just fine in the beginning of the text, but as the string becomes longer and longer, then, the blinking issues appear to the viewer!"
Private Sub AppTxtThread()
While (Counter < String1.Length)
AppText(String1(Counter))
Thread.Sleep(100)
Counter += 1
End While
End Sub
Private Sub AppText(ByVal [text] As String)
If TextBox1.InvokeRequired Then
Dim d As New AppTextCallback(AddressOf AppText)
Me.Invoke(d, New Object() {[text]})
Else
TextBox1.Select()
TextBox1.AppendText([text])
TextBox1.SelectionStart = TextBox1.Text.Length
End If
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Thread1 = New Thread(AddressOf AppTxtThread)
Thread1.IsBackground = True
Thread1.Start()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Counter = 0
TextBox1.Select()
While (Counter < String1.Length)
TextBox1.AppendText(String1(Counter))
TextBox1.SelectionStart = TextBox1.Text.Length
Thread.Sleep(100)
Counter += 1
End While
End Sub
End Class
Am I gone wrong somewhere?
Is there anything else I should do?
Yet another problem:
if I use
Form2.CheckBox2.Checked
in the
AppTxtThread
it always gives
True
value (which is its Form_Loaded primary value), no matter you've changed it in a non-thread function or not.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[ EDITS: UPDATING CODE, USING PROPER INVOKING WAY; USING STRING BUILDER ]
Well, I wrote a newer code, but there are some parts that I couldn't handle via googling:
-
ManualResetEvent
, I read about it, but how do I implement it? It has just five classes including
WaitAny
. How does it pauses/resumes or restarts threads? I have now used an un-safe way to suspend the thread temporarily.
-
StringBuilder
, how to assign it to the
Textbox.Text
? I added binding to the Text, but on
SB.Append()
nothing happens in the TextBox, that's why I had to use
=
funcion for now (I know this is not good!).
- Is
IsBackground
necessary for Thread1?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[ EDITS: UPDATING CODE, USING WAIT HNDLERS ]
Okay, I used a
ManualResetEvent
to Pause/Play the Thread.
I found
this article and
this one useful for the case.
Here's the new Code:
Imports System.Threading
Public Class Form1
Public Delegate Sub AppendDelegate(ByVal aString As Char)
Public Delegate Sub CheckSetDelegate(ByVal Status As Boolean)
Dim Thread1 As Thread
Dim C As Short
Dim String1 As String = "This string is typed using threads. How is the performance?"
Dim WaitHandle As ManualResetEvent
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Thread1 = New Thread(AddressOf AppTxtThread)
WaitHandle = New ManualResetEvent(False)
End Sub
Private Sub AppTxtThread()
While (C < String1.Length)
WaitHandle.WaitOne()
TextBox1.Invoke(New AppendDelegate(AddressOf AppendTxt), String1(C))
C += 1
Thread.Sleep(100)
End While
CheckBox1.Invoke(New CheckSetDelegate(AddressOf CheckboxSet), False)
C = 0
End Sub
Private Sub AppendTxt(ByVal Chr As Char)
TextBox1.AppendText(Chr)
End Sub
Private Sub CheckboxSet(ByVal Stat As Boolean)
If Stat = False Then
CheckBox1.Checked = False
Else
CheckBox1.Checked = True
End If
End Sub
Private Sub CheckToggled(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.Checked Then
If Thread1.ThreadState = ThreadState.Unstarted Then
Thread1.Start()
ElseIf Thread1.ThreadState = ThreadState.Stopped Then
Thread1 = New Thread(AddressOf AppTxtThread)
Thread1.Start()
End If
WaitHandle.Set()
Else
WaitHandle.Reset()
End If
End Sub
End Class