Vb.net 更改控件';通过委托创建属性

Vb.net 更改控件';通过委托创建属性,vb.net,Vb.net,首先,如果我的英语不好,请原谅,我不是以英语为母语的人 我对编程相当陌生,我正在尝试自学VB.NET 我在试图了解代表时遇到了一个问题。(见下面的代码) 我试图完成的是通过线程更新指定控件的文本属性。但是,一旦启动线程,就会出现ArgumentException错误。我完全不知道怎么了。有人知道我做错了什么吗 Public Class Form1 Delegate Sub myDelegate1(ByVal s_Name As Control, ByVal s_txt As String) P

首先,如果我的英语不好,请原谅,我不是以英语为母语的人

我对编程相当陌生,我正在尝试自学VB.NET 我在试图了解代表时遇到了一个问题。(见下面的代码)

我试图完成的是通过线程更新指定控件的文本属性。但是,一旦启动线程,就会出现ArgumentException错误。我完全不知道怎么了。有人知道我做错了什么吗

Public Class Form1

Delegate Sub myDelegate1(ByVal s_Name As Control, ByVal s_txt As String)
Public txtUpdate As New myDelegate1(AddressOf upd_ControlTextProperty)

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Label1.Text = vbnullstring
End Sub

Private Sub upd_ControlTextProperty(ByVal ControlName As Control, ByVal txt As String)
    ControlName.Text = txt
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim thread1 As New Threading.Thread(AddressOf threadstart)
    thread1.IsBackground = True
    thread1.Start()

End Sub

Private Sub threadstart()
        Me.Invoke(Me.txtUpdate, New Object(), {Label1, "This is Label 1"})
End Sub

End Class

正如ValyreanGroup所说,您的代表应该接受两个参数,然后您传递三个:

Me.Invoke(Me.txtUpdate, New Object(), {Label1, "This is Label 1"})
          ^-1--------^  ^-2--------^  ^-3-----------------------^
因此,只需删除
新对象()
对象,并将此
{Label1,…}
转换为一个字符串:

Me.Invoke(Me.txtUpdate, "This is Label 1")
好吧,这样更好

另一方面,你所做的不是很有用

  • 您可以从UI线程创建一个新线程
  • 有了这个新线程,您可以调用回UI线程并停止线程
请记住,控件只能由创建表单的线程(UI线程)更新

除非您有充分的理由使用后台线程,否则您可以将代码恢复到:

Public Class Form1

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Label1.Text = vbnullstring
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Label1.Text = "This is Label 1"
End Sub

End Class
更新 (来自评论)

更清楚地说,这里有一个模式(我采用了这个模式,如果有任何限制,我将删除该图像)

主UI线程用于以下各项:

  • 对用户事件(点击、输入…)做出反应,并启动执行该过程的后台线程
  • 在后台线程结束或任务期间更新用户界面

当我说你所做的没有用是因为你的后台线程没有做任何处理,它只是通知UI线程更新UI…

我会尝试这种方法。可以从UI线程或新线程成功调用upd_ControlTextProperty

Public Class Form1

Delegate Sub myDelegate1(ByVal s_Name As Control, ByVal s_txt As String)
Public txtUpdate As New myDelegate1(AddressOf upd_ControlTextProperty)

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Label1.Text = ""
End Sub

Private Sub upd_ControlTextProperty(ByVal ControlName As Control, ByVal txt As String)
    If Me.InvokeRequired = True Then
        Me.Invoke(txtUpdate, New Object() {ControlName, txt})
    Else
        ControlName.Text = txt
    End If
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim thread1 As New Threading.Thread(AddressOf threadstart)
    thread1.IsBackground = True
    thread1.Start()
End Sub

Private Sub threadstart()
    upd_ControlTextProperty(Label1, "This is Label 1")
End Sub

End Class

你传递了3个参数,但是回调只需要2个。这让我很困惑,msdn的一个例子也传递了3个参数,但是回调只需要1个。嘿,谢谢你!我理解,使用按钮单击事件或从表单本身更新控件的属性更简单。这只是我理解和应用学员的一个练习。另一方面,为什么说从UI线程创建一个新线程没有用呢?我的意思是,线程应该在哪里创建?你能详细说明一下吗?从UI线程开始一个新线程没有问题。这个问题更多的是为了新线程的目的,它被设计为同时运行两个异步进程。如果新线程的主要目的是更新UI,那么将有对UI线程的连续回调来执行更新。因此,在第二个线程上运行这样的操作不是最佳的,因为UI更新可以由单个UI线程处理。@printf更新了我的答案,以便您可以更清楚地了解后台线程的使用