Hello everyone,
I've been crunching this issue through my brain for a day or so now. For simplicity, I took the problem out into a separate project to try to isolate the bug.
I have two forms, Output and Input. Output is the main form and contains two textboxes and a button. Clicking the button opens the second modal form, Input. On this form there exists several buttons and two textboxes. The buttons are labeled Start, End, and Toggle. The Start button begins a background worker that constantly looks at the state of a boolean variable, Toggle, that is controlled by, you guess it, the toggle button. The End button simply kills the thread. The purpose is to be able to switch the text and colors of the two textboxes on the OUTPUT form by clicking the toggle button on the INPUT form. For whatever reason, I cannot get them to change. The two textboxes on the INPUT form are simply there for my own sanity; to know that the delegates I have written actually work, but again, the two textboxes on the OUTPUT form wont change.
Here is the code from both forms:
Output form
Input form
As you can see, I have written delegates to determine if Invoke is required. When I step through I have found that the delegate will return Textbox.InvokeRequired as False when it should be True. I read that this can be cause by the controls handle not having been created yet, and to use the check If Textbox.IsHandleCreated in the delegate, but I do not believe this is the problem.
If anyone can provide any insight, it would be much appreciated.
Thanks,
Wes
I've been crunching this issue through my brain for a day or so now. For simplicity, I took the problem out into a separate project to try to isolate the bug.
I have two forms, Output and Input. Output is the main form and contains two textboxes and a button. Clicking the button opens the second modal form, Input. On this form there exists several buttons and two textboxes. The buttons are labeled Start, End, and Toggle. The Start button begins a background worker that constantly looks at the state of a boolean variable, Toggle, that is controlled by, you guess it, the toggle button. The End button simply kills the thread. The purpose is to be able to switch the text and colors of the two textboxes on the OUTPUT form by clicking the toggle button on the INPUT form. For whatever reason, I cannot get them to change. The two textboxes on the INPUT form are simply there for my own sanity; to know that the delegates I have written actually work, but again, the two textboxes on the OUTPUT form wont change.
Here is the code from both forms:
Output form
Code:
Public Class OutputFrm
Public Delegate Sub SetTextBoxText_Delegate(ByVal [TextBox] As TextBox, ByVal [text] As String)
Public Delegate Sub SetTextboxColor_Delegate(ByVal [TextBox] As TextBox, ByVal [color] As Drawing.Color)
Public Sub SetTextBoxColor_ThreadSafe(ByVal [TextBox] As TextBox, ByVal [color] As Drawing.Color)
If [TextBox].InvokeRequired Then
Dim Mydelegate As New SetTextboxColor_Delegate(AddressOf SetTextBoxColor_ThreadSafe)
Me.Invoke(Mydelegate, New Object() {[TextBox], [color]})
Else
[TextBox].BackColor = [color]
End If
End Sub
' Delagate subs
Public Sub SetTextBoxText_ThreadSafe(ByVal [TextBox] As TextBox, ByVal [text] As String)
If [TextBox].InvokeRequired Then
Dim Mydelegate As New SetTextBoxText_Delegate(AddressOf SetTextBoxText_ThreadSafe)
Me.Invoke(Mydelegate, New Object() {[TextBox], [text]})
Else
[TextBox].Text = [text]
End If
End Sub
Private Sub ModalBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ModalBtn.Click
InputFrm.ShowDialog()
End Sub
End ClassCode:
Public Class InputFrm
Dim Toggle As Boolean = False
Public Delegate Sub SetTextBoxText_Delegate(ByVal [TextBox] As TextBox, ByVal [text] As String)
Public Delegate Sub SetTextboxColor_Delegate(ByVal [TextBox] As TextBox, ByVal [color] As Drawing.Color)
Public Sub SetTextBoxColor_ThreadSafe(ByVal [TextBox] As TextBox, ByVal [color] As Drawing.Color)
If [TextBox].InvokeRequired Then
Dim Mydelegate As New SetTextboxColor_Delegate(AddressOf SetTextBoxColor_ThreadSafe)
Me.Invoke(Mydelegate, New Object() {[TextBox], [color]})
Else
[TextBox].BackColor = [color]
End If
End Sub
' Delagate subs
Public Sub SetTextBoxText_ThreadSafe(ByVal [TextBox] As TextBox, ByVal [text] As String)
If [TextBox].InvokeRequired Then
Dim Mydelegate As New SetTextBoxText_Delegate(AddressOf SetTextBoxText_ThreadSafe)
Me.Invoke(Mydelegate, New Object() {[TextBox], [text]})
Else
[TextBox].Text = [text]
End If
End Sub
Private Sub StartBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartBtn.Click
TestWorker.RunWorkerAsync()
End Sub
Private Sub StopBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopBtn.Click
TestWorker.CancelAsync()
End Sub
Public Sub TestWorker_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles TestWorker.DoWork
Do
If Toggle Then
'These are the ones I'm actually trying to toggle
OutputFrm.SetTextBoxText_ThreadSafe(OutputFrm.TB1, "I'm an apple!")
OutputFrm.SetTextBoxColor_ThreadSafe(OutputFrm.TB1, Color.Firebrick)
OutputFrm.SetTextBoxText_ThreadSafe(OutputFrm.TB2, "I'm a banana")
OutputFrm.SetTextBoxColor_ThreadSafe(OutputFrm.TB2, Color.LimeGreen)
'These are just for my own sanity
SetTextBoxText_ThreadSafe(TB1, "I'm an apple!")
SetTextBoxColor_ThreadSafe(TB1, Color.Firebrick)
SetTextBoxText_ThreadSafe(TB2, "I'm a banana")
SetTextBoxColor_ThreadSafe(TB2, Color.LimeGreen)
Else
'These are the ones I'm actually trying to toggle
OutputFrm.SetTextBoxText_ThreadSafe(OutputFrm.TB2, "I'm an apple!")
OutputFrm.SetTextBoxColor_ThreadSafe(OutputFrm.TB2, Color.Firebrick)
OutputFrm.SetTextBoxText_ThreadSafe(OutputFrm.TB1, "I'm a banana")
OutputFrm.SetTextBoxColor_ThreadSafe(OutputFrm.TB1, Color.LimeGreen)
'These are just for my own sanity
SetTextBoxText_ThreadSafe(TB2, "I'm an apple!")
SetTextBoxColor_ThreadSafe(TB2, Color.Firebrick)
SetTextBoxText_ThreadSafe(TB1, "I'm a banana")
SetTextBoxColor_ThreadSafe(TB1, Color.LimeGreen)
End If
If TestWorker.CancellationPending Then
Exit Do
End If
Loop
End Sub
Private Sub ToggleBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ToggleBtn.Click
If Toggle Then
Toggle = False
Else
Toggle = True
End If
End Sub
End ClassIf anyone can provide any insight, it would be much appreciated.
Thanks,
Wes