在Windows Forms应用程序开发中,经常会遇到需要在非主线程中更新界面控件的情况。然而,直接在非主线程中操作界面控件可能会导致线程冲突,从而引发错误。本文将介绍一种线程安全的方法来更新Windows表单控件的属性,即使在非主线程中进行操作。
在Windows Forms应用程序中,所有的控件都是在主线程中创建的。如果在非主线程中尝试更新控件的属性,可能会遇到线程冲突的问题。虽然有时不会立即报错,但这种潜在的问题可能会导致程序在运行过程中出现不可预知的错误。为了避免这种情况,需要一种线程安全的方式来更新控件的属性。
以下情况可能会用到这种方法:
为了解决这个问题,可以创建一个通用的类,用于在任何线程中安全地更新控件的属性。这个类的核心思想是使用委托(Delegate)和异步调用(BeginInvoke)来确保控件属性的更新操作在主线程中执行。
以下是实现线程安全更新控件属性的步骤:
以下是实现线程安全更新控件属性的完整代码示例:
Imports System.Windows.Forms
Public Class cThreadsafe_WinForm_Controls
Private pInvokeTestLabel As Label
Private mMyForm As Form
Public Enum ControlProperties
Visible
Enabled
Text
' 其他需要的属性
End Enum
Public Sub New(ByRef A_Form As Form)
mMyForm = A_Form
pInvokeTestLabel = New Label
mMyForm.Controls.Add(pInvokeTestLabel)
pInvokeTestLabel.Visible = False
End Sub
Public Delegate Sub Safely_SetControlProperty_delegate(ByRef C As Control, ByVal P As ControlProperties, NewValue As Object)
Public Sub Safely_SetControlProperty(ByRef C As Control, ByVal P As ControlProperties, ByVal NewValue As Object)
If pInvokeTestLabel.InvokeRequired Then
Dim ThisSub As New Safely_SetControlProperty_delegate(AddressOf Safely_SetControlProperty)
pInvokeTestLabel.BeginInvoke(ThisSub, New Object() {C, P, NewValue})
Else
Select Case P
Case ControlProperties.Enabled
C.Enabled = CType(NewValue, Boolean)
Case ControlProperties.Text
C.Text = CType(NewValue, String)
Case ControlProperties.Visible
C.Visible = CType(NewValue, Boolean)
End Select
End If
End Sub
End Class
Private mControlSetter As cThreadsafe_WinForm_Controls
Private Sub Form_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
mControlSetter = New cThreadsafe_WinForm_Controls(Me)
End Sub
' 在需要更新控件属性的地方调用
mControlSetter.Safely_SetControlProperty(C:=pnlConnectedOrNot, P:=cThreadsafe_WinForm_Controls.ControlProperties.Visible, NewValue:=False)