When using multithreading to Improve the Performance of Windows Forms applications, you must call the control in thread-safe mode.
Example
Access to Windows Forms controls is not thread-safe in nature. If two or more threads operate on the status of a control, the control may be forced to enter an inconsistent state. Other thread-related bugs may also occur, including contention and deadlocks. It is important to ensure that controls are accessed in a thread-safe manner.
. NET Framework helps detect this issue when accessing controls in a non-thread-safe manner. When running an application in the debugger, if a thread other than the thread that creates a control tries to call the control, the debugger will throw an invalidoperationexception and prompt the message: "it is never accessed by the thread that creates the control name of the control."
This exception occurs reliably during debugging and in some cases during runtime. We strongly recommend that you fix this issue when this error message is displayed. This exception may occur when you debug applications written in. NET Framework before. NET Framework 2.0.
Note:
You can disable this exception by setting the value of the checkforillegalcrossthreadcils attribute to false. This causes the control to run in the same way as in Visual Studio 2003.
The following code example demonstrates how to call a Windows form control from a third thread in the thread-safe and non-thread-safe mode. It demonstrates a method to set the text attribute of the Textbox Control in non-thread security mode, and two methods to set the text attribute in thread security mode.
Copy code in Visual Basic
Imports system
Imports system. componentmodel
Imports system. threading
Imports system. Windows. Forms
Public class form1
Inherits form
'This delegate enables asynchronous callfor setting
'The text property on a Textbox Control.
Delegate sub settextcallback ([text] as string)
'This thread is used to demonstrate both thread-safe and
'Unsafe ways to call a Windows Forms control.
Private demothread as thread = nothing
'This backgroundworker is used to demonstrate
'Preferred way of parameter Ming asynchronous operations.
Private withevents backgroundworker1 as backgroundworker
Private textbox1 as textbox
Private withevents settextunsafebtn as button
Private withevents settextsafebtn as button
Private withevents settextbackgroundworkerbtn as button
Private components as system. componentmodel. icontainer = nothing
Public sub new ()
Initializecomponent ()
End sub
Protected overrides sub dispose (disposing as Boolean)
If disposing andalso not (components is nothing) then
Components. Dispose ()
End if
Mybase. Dispose (disposing)
End sub
'This event handler creates a thread that calla
'Windows Forms control in an unsafe way.
Private Sub setTextUnsafeBtn_Click (_
ByVal sender As Object ,_
ByVal e As EventArgs) Handles setTextUnsafeBtn. Click
Me. demoThread = New Thread (_
New ThreadStart (AddressOf Me. ThreadProcUnsafe ))
Me. demoThread. Start ()
End Sub
'This method is executed on the worker thread and makes
An unsafe call on the TextBox control.
Private sub threadprocunsafe ()
Me. textbox1.text = "this text was set unsafely ."
End sub
'This event handler creates a thread that calla
'Windows forms control in a thread-safe way.
Private sub settextsafebtn_click (_
Byval sender as object ,_
Byval e as eventargs) handles settextsafebtn. Click
Me. demothread = new thread (_
New threadstart (addressof me. threadprocsafe ))
Me. demothread. Start ()
End sub
'This method is executed on the worker thread and makes
'A thread-safe call on the Textbox Control.
Private sub threadprocsafe ()
Me. settext ("this text was set safely .")
End sub
'This method demonstrates a pattern for making thread-safe
'Calls on a Windows Forms control.
'
'If the calling thread is different from the thread that
'Created the Textbox Control, this method creates
'Settextcallback and callitself asynchronously using
'Invoke method.
'
'If the calling thread is the same as the thread that created
'The TextBox control, the Text property is set directly.
Private Sub SetText (ByVal [text] As String)
'Invokerequired required compares the thread ID of
'Calling thread to the thread ID of the creating thread.
'If these threads are different, it returns true.
If Me. textBox1.InvokeRequired Then
Dim d As New SetTextCallback (AddressOf SetText)
Me. Invoke (d, New Object () {[text]})
Else
Me. textBox1.Text = [text]
End If
End Sub
'This event handler starts the form's
'Backgroundworker by calling RunWorkerAsync.
'
'The Text property of The TextBox control is set
'When the BackgroundWorker raises the RunWorkerCompleted
'Event.
Private Sub setTextBackgroundWorkerBtn_Click (_
ByVal sender As Object ,_
ByVal e As EventArgs) Handles setTextBackgroundWorkerBtn. Click
Me. backgroundWorker1.RunWorkerAsync ()
End Sub
'This event handler sets the Text property of the TextBox
'Control. It is called on the thread that created
'Textbox control, so the call is thread-safe.
'
'Backgroundworker is the preferred way to perform asynchronous
'Operations.
Private Sub backgroundworkerappsrunworkercompleted (_
ByVal sender As Object ,_
ByVal e As RunWorkerCompletedEventArgs )_
Handles backgroundWorker1.RunWorkerCompleted
Me. textBox1.Text = _
"This text was set safely by BackgroundWorker ."
End sub
# Region "Windows Form Designer generated code"
Private sub initializecomponent ()
Me. textbox1 = new system. Windows. Forms. Textbox ()
Me. settextunsafebtn = new system. Windows. Forms. Button ()
Me. settextsafebtn = new system. Windows. Forms. Button ()
Me. settextbackgroundworkerbtn = new system. Windows. Forms. Button ()
Me. backgroundworker1 = new system. componentmodel. backgroundworker ()
Me. suspendlayout ()
'
'Textbox1
'
Me. textbox1.location = new system. Drawing. Point (12, 12)
Me. textbox1.name = "textbox1"
Me. textbox1.size = new system. Drawing. Size (240, 20)
Me. textbox1.tabindex = 0
'
'Settextunsafebtn
'
Me. settextunsafebtn. Location = new system. Drawing. Point (15, 55)
Me. settextunsafebtn. Name = "settextunsafebtn"
Me. settextunsafebtn. tabindex = 1
Me. settextunsafebtn. Text = "unsafe call"
'
'Settextsafebtn
'
Me. settextsafebtn. Location = new system. Drawing. Point (96, 55)
Me. settextsafebtn. Name = "settextsafebtn"
Me. settextsafebtn. tabindex = 2
Me. settextsafebtn. Text = "safe call"
'
'Settextbackgroundworkerbtn
'
Me. settextbackgroundworkerbtn. Location = new system. Drawing. Point (177, 55)
Me. settextbackgroundworkerbtn. Name = "settextbackgroundworkerbtn"
Me. settextbackgroundworkerbtn. tabindex = 3
Me. settextbackgroundworkerbtn. Text = "Safe BW call"
'
'Backgroundworker1
'
'
'Form1
'
Me. clientsize = new system. Drawing. Size (268, 96)
Me. Controls. Add (settextbackgroundworkerbtn)
Me. Controls. Add (settextsafebtn)
Me. Controls. Add (settextunsafebtn)
Me. Controls. Add (textbox1)
Me. Name = "form1"
Me. Text = "form1"
Me. resumelayout (false)
Me. Merge mlayout ()
End sub 'initializecomponent
# End Region
<Stathread ()> _
Shared sub main ()
Application. enablevisualstyles ()
Application. Run (New form1 ())
End sub
End Class