使用另一个 class VB.Net 中的方法通过 Background Worker 更新主窗体上的控件

Update control on main form via Background Worker with method in another class VB.Net

我整天都在用头撞墙试图弄清楚这个问题。

我正在完成一个程序来简单地删除特定临时文件夹中的文件。我读过,有时为方法和变量创建单独的 classes 是一种很好的做法。因此,我为几种方法创建了一个单独的 class 来删除指定目录中的文件和文件夹。我在我的 Form1 class 中使用后台工作者,并从我的 WebFixProcesses 调用我的 deleteFiles() 方法 class 在 DoWork 事件中 Form1 class。我正在使用 Background Worker,以便我可以轻松地将进度报告回主窗体上的进度条。

文件被删除没有问题,但我无法在主窗体上获得标签以反映当前正在删除的文件。标签不会以任何方式改变。 我知道公式是正确的,因为如果方法在 Form1 class 中,我可以使它正常工作。我只是使用:

 Invoke(Sub()
     lblStatus.Text = File.ToString
     lblStatus.Refresh()
 End Sub)

这是我从 WebFixProcesses class:

调用的方法
Public Shared Sub deleteFiles(ByVal fileLocation As String)
    For Each file As String In Directory.GetFiles(fileLocation)
        Try

            fileDisplay.Add(file)
            For i = 1 To fileDisplay.Count
                file = fileDisplay(i)
                Form1.BackgroundWorker1.ReportProgress(CInt(i / fileDisplay.Count) * 100)

            Next
            IO.File.Delete(file)                
            Form1.labelText(file)
            Form1.labelRefresh()

        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    Next
End Sub

labelText()labelRefresh() 是我的主窗体中使用委托尝试将信息传递给控件的方法:

Public Sub labelText(ByVal file As String)
    If lblStatus.InvokeRequired Then
        Dim del As New txtBoxDelegate(AddressOf labelText)
        Me.Invoke(del, file)
    Else
                   lblStatus.Text = file.ToString()
    End If

End Sub
Public Sub labelRefresh()
    If lblStatus.InvokeRequired Then
        Dim del As New txtBoxRefDelegate(AddressOf labelRefresh)
        Me.Invoke(del)
    Else
                   lblStatus.Refresh()

    End If
End Sub

如果有人能帮助我告诉我我可能做错了什么,我将不胜感激,因为我的头因此而痛苦不堪。也许我做错了,只是固执地把我的方法留在他们自己的地方 class。但任何帮助都会很棒。谢谢大家!

Hans 在问题评论中写的是真的:Form1 是一个 type,不是 instance,而是为了让新程序更容易(来自 VB6),M$ 做了一个 "mix",允许您在主线程中使用表单名称作为表单的实例。

然而,这仅在您在 that 线程上时有效。

如果您从 另一个 线程引用 Form1,则会创建 Form1 的新实例。

要解决此问题,请将此代码添加到表单中:

Private Shared _instance As Form1
Public ReadOnly Property Instance As Form1
    Get
        Return _instance
    End Get
End Property

我们将使用此 属性 来存储表单的当前实例。为此,将此行添加到 Load 事件:

Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    _instance = Me

    'other code here
End Sub

现在,从每个 class,在任何线程中,如果您使用

Form1.Instance

...你得到了实际的形式。现在你可以 Invoke,即使是同一个表格:

    Me.instance.Invoke(Sub()
                           Me.lblStatus.Text = "Hello World"
                       End Sub)