我不确定从UI线程调用此代码的原因,但不是这样:
Delegate Sub CtrlPropertyChangeDelegate(ByRef ControlProperty As Object, ByVal NewValue As Object)
Sub CtrlPropertyChange(ByRef ControlProperty As Object, ByVal NewValue As Object)
If Me.InvokeRequired Then
Me.Invoke(New CtrlPropertyChangeDelegate(AddressOf CtrlPropertyChange), ControlProperty, NewValue)
Else
ControlProperty = NewValue
End If
End Sub
它应该使用控件的属性(例如Form1.Text)并更改其值。任何帮助将不胜感激
答案 0 :(得分:1)
更新以合并@VisualVincent's Extension,应将其标记为正确答案。
Public Class Form1
Private Rand As New Random
Private Done As Boolean = True
Private WordList() As String = {"One", "Two", "Three", "Four"}
Private Colors() As Color = {Color.Red, Color.Blue, Color.Gray, Color.Yellow}
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Done Then
Done = False
Task.Run(Sub() DoSomething())
Else
Done = True
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
RandomChange()
End Sub
Sub DoSomething()
Me.Button1.SetProperty("Text", "Stop")
Do Until Done
RandomChange()
Threading.Thread.Sleep(1000)
Loop
Me.Button1.SetProperty("Text", "Start")
End Sub
Sub RandomChange()
Select Case Rand.Next(1, 6)
Case 1
Me.ProgressBar1.SetProperty("Value", Rand.Next(10, 90))
Case 2
Me.TextBox1.SetProperty("Text", WordList(Rand.Next(0, 4)))
Case 3
Me.Label1.SetProperty("Text", WordList(Rand.Next(0, 4)))
Case 4
Me.CheckBox1.SetProperty("Checked", Not Me.CheckBox1.Checked)
Case 5
Me.SetProperty("BackColor", Colors(Rand.Next(0, 4)))
End Select
End Sub
End Class
答案 1 :(得分:1)
正如我的评论中已经提到的,一旦您将ControlProperty
传递给Control.Invoke()
的参数,就不再通过引用传递它。
这是使用Reflection的解决方案。您只需将属性的名称和要传递给SetProperty
方法的值传递给它。我已将其声明为扩展方法,因此必须将其放入公共模块中:
Imports System.Reflection
Imports System.Runtime.CompilerServices
Public Module Extensions
''' <summary>
''' Thread-safely sets the property of a control to the specified value. Be sure that the value is of the correct type.
''' </summary>
''' <param name="Control">The control which's property to set.</param>
''' <param name="PropertyName">The name of the property to set.</param>
''' <param name="Value">The value to give the property.</param>
<Extension()> _
Public Sub SetProperty(ByVal Control As Control, ByVal PropertyName As String, ByVal Value As Object)
If Control.InvokeRequired = True Then
Control.Invoke(Sub() Control.SetProperty(PropertyName, Value))
Else
Control.GetType().InvokeMember(PropertyName, _
BindingFlags.SetProperty _
Or BindingFlags.IgnoreCase _
Or BindingFlags.Public _
Or BindingFlags.Instance _
Or BindingFlags.Static, _
Nothing, Control, New Object() {Value})
End If
End Sub
End Module
现在您可以像这样使用它:
For x = 1 To 256
Label1.SetProperty("Text", ((x * 100) / 256) & "%")
ProgressBar1.SetProperty("Value", x)
Thread.Sleep(15)
Next
重要提示:使用此功能时,必须确保您提供属性的值的类型正确,因为不会执行隐式转换。因此,如果您设置的属性属于String
类型,则尝试将其设置为Integer
将引发异常。