Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从.NET中的另一个线程更改UI元素_.net_Vb.net_Multithreading_User Interface_Delegates - Fatal编程技术网

从.NET中的另一个线程更改UI元素

从.NET中的另一个线程更改UI元素,.net,vb.net,multithreading,user-interface,delegates,.net,Vb.net,Multithreading,User Interface,Delegates,我不明白。如果我想从VisualBasic.NET中的UI线程以外的线程更改按钮上的文本,我需要使用委托,并按照 Private Delegate Sub SetTextDelegate(ByVal TheText As String) Private Sub delSetText(ByVal TheText As String) Button1.Text = TheText End Sub Private Sub ChangeText(ByVal TheText As St

我不明白。如果我想从VisualBasic.NET中的UI线程以外的线程更改按钮上的文本,我需要使用委托,并按照

 Private Delegate Sub SetTextDelegate(ByVal TheText As String)
 Private Sub delSetText(ByVal TheText As String)
     Button1.Text = TheText
 End Sub

 Private Sub ChangeText(ByVal TheText As String)
     If Button1.InvokeRequired Then
         Me.BeginInvoke(New SetTextDelegate(AddressOf delSetText), TheText)
     Else
         delSetText(TheText)
     End If
 End Sub
当然,我可以制作更多的通用函数,而不是硬连接的。但是,似乎还是需要大量的打字。我是不是在绕圈子?这怎么不包括在控件属性中?如果需要,为什么会有人把它留给程序员呢?

在C#中,匿名方法在这里非常有用;也许VB中也有类似的东西?(我的VB-fu很弱)。您还可以重复使用当前方法,而不是使用两种方法;例如:

void ChangeText(string text) {
    if(InvokeRequired) {
        this.Invoke((MethodInvoker) delegate {ChangeText(text);});
    } else {
        Button1.Text = text;
    }
}
请注意,我在这里特意使用了
MethodInvoker
——这是
Invoke
作为特例处理的,这意味着它不必使用(非常慢的)
DynamicInvoke


我也可以用anon方法做
.Text=Text
,但这似乎违反了DRY。

这是正确的方法。跨线程操作被禁用,因为在线程之间共享数据是危险的。这就是为什么要创建一个委托来封送对主线程的调用,主线程拥有您试图访问的控件。如果您不喜欢为每个调用创建一个委托,那么您可以编写某种类型的通用包装器来为您处理此功能。就像@Marc Gravell所说的,您不需要delSetText方法,您可以只使用ChangeText的Else子句中的Button1.Text=TheText。我仍然不明白为什么我必须完成所有这些工作来完成一些总是需要的事情。也就是说,如果我要从另一个线程更改按钮的文本,我必须这样做。那么,为什么还要给最终用户这个选项呢?似乎唯一节省时间的方法是创建从每个控件继承的新类,并重写所有需要此类委托才能实现线程安全的属性。我是否遗漏了一些基本的东西?从技术上讲,这并不总是必需的。您可以通过将控件上的CheckForIllegalCrossThreadCalls属性设置为false来禁用此功能。但是,这通常意味着您正在做两件事中的一件:调试代码时,不希望在调试过程中遇到此异常,或者手动锁定共享资源。顺便说一下,我刚刚看到了这一点:对于所有程序来说,将其设置为true可能是一个好习惯,以避免以后出现头痛。我早就应该切换到C#了。但是VB是一个很难改掉的习惯。谢谢