VB.NET委托和调用 - 有人可以向我解释这些吗?

syn*_*ica 6 vb.net delegates invoke backgroundworker

我是线程世界的新手,但我正在研究的应用程序的一些方面要求我使用BackgroundWorker控件来防止UI在执行某些文件操作时冻结.

我要做的是从BackgroundWorker中更新几个表单标签.从来没有使用过这个之前我很快发现我无法访问未在同一个线程中创建的控件,因此经过一些研究后我实现了以下代码,似乎可以使一切工作:

Private Delegate Sub DelegateUpdateStatus(ByVal statusText As String, ByRef currentFile As String)

Private Sub UpdateStatus(ByVal statusText As String, ByVal currentFile As String)

    If InvokeRequired Then
        Invoke(Sub() LblStatus.Text = statusText)
        Invoke(Sub() LblCurrentFile.Text = currentFile)
    Else
        LblStatus.Text = statusText
        LblCurrentFile.Text = currentFile
    End If

End Sub
Run Code Online (Sandbox Code Playgroud)

但事情是,我不知道这个代码在做什么,或者为什么需要它.

我做了一些研究,但我没有做过任何真正的工作,我读过的大多数文章都假设了一些先验知识.

我希望了解的三个主要内容:

  • 为什么需要此代码(例如,为什么无法直接从BackgroundWorker访问控件)
  • 委托是什么,何时需要使用它
  • Invoke方法的作用,以及我使用InvokeRequired检查的内容

如上所述,线程仍然是一个非常外国的概念,所以任何简单的英语答案都会非常有用 - 谢谢!

编辑:感谢大家到目前为止的回复.我已经做了一些进一步的阅读,我想知道我是否正确地采用了这种方式.我使用BackgroundWorker的原因是为了确保在我执行文件操作时UI保持响应.问题是,我仍然需要等到BackgroundWorker完成它的工作,所以我可以返回一个指示操作成功的布尔值.有办法解决这个问题,但是从我的阅读中,不得不等待BackgroundWorker完成它的工作就是首先要破坏使用它的目的.那么,阻止UI锁定的最佳方法是什么?

Adr*_*der 12

好了,到目前为止做得很好.

让我们从第1点开始.

如何:对Windows窗体控件进行线程安全调用

如果使用多线程来提高Windows窗体应用程序的性能,则必须确保以线程安全的方式调用控件.

对Windows窗体控件的访问本质上不是线程安全的.如果有两个或多个线程操纵控件的状态,则可以强制控件进入不一致状态.

因此,正如您所看到的,您需要确保在更改控件的状态时,以线程安全的方式完成.

现在,属性Control.InvokeRequired检查您正在执行的代码是否与最初创建该控件的代码位于不同的线程上.

如果是,我们需要一些方法来调用原始线程上的代码.

因此,您需要使用Control.Invoke方法在原始线程上执行此类代码.

在拥有控件的基础窗口句柄的线程上执行委托.

现在问题是,您需要告诉该线程它应该执行什么,这是使用委托完成的.

表示委托,它是一个引用静态方法或类实例的数据结构,以及该类的实例方法.

现在,我建议的最后一件事是你看看代理,匿名代表,匿名方法和Lamda表达式之间的区别.


One*_*Day 4

InvokeRequired询问“我在正确的线程上吗?”,如果是这样继续,否则我需要一个委托 - 在你的代码中你会看到一个 lambda Sub

 Invoke(Sub() LblStatus.Text = statusText)
Run Code Online (Sandbox Code Playgroud)

另一种可行的方法是将结果定向到 diff Sub 例程(其中委托已交叉到正确的线程),但在这里我们可以在 Invoke 方法本身内运行 Sub - 只是一种更简单的方法它。

每当您使用单独的线程执行异步工作时,都需要委托。

调用-MSDN