通过另一个类VB.Net中的方法通过后台工作程序更新主窗体上的控件

通过另一个类VB.Net中的方法通过后台工作程序更新主窗体上的控件,vb.net,class,thread-safety,backgroundworker,Vb.net,Class,Thread Safety,Backgroundworker,我一整天都在拼命想办法弄明白这件事 我正在完成一个程序,只需删除特定临时文件夹中的文件。我已经读到,有时为方法和变量创建单独的类是一种很好的做法。因此,我为几个方法创建了一个单独的类来删除指定目录中的文件和文件夹。我在我的Form1类中使用后台工作程序,并在Form1类中的DoWork事件中从我的WebFixProcesses类调用我的deleteFiles()方法。我正在使用后台工作程序,以便可以轻松地将进度报告回主窗体上的进度栏 文件被删除时没有问题,但我无法在主窗体上获得反映当前被删除文件

我一整天都在拼命想办法弄明白这件事

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

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

 Invoke(Sub()
     lblStatus.Text = File.ToString
     lblStatus.Refresh()
 End Sub)
下面是我从WebFixProcesss类调用的方法:

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

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

Hans在问题评论中所写的是正确的:
Form1
是一种类型,而不是实例,但为了使NewBy程序(来自VB6),M$进行了“混合”,允许您在主线程中使用表单名称作为表单实例

但是,只有当您在该线程上时,这才有效

如果从另一个线程引用
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
现在,从每个类,在任何线程中,如果您使用

Form1.Instance
…你得到了真实的形式。现在您可以
调用
,即使是从相同的表单:

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

可能是标准VB.NET问题的重复,我们以大约每周2次的速度得到它们。总是不同的代码,总是相同的问题。labelText(文件)是一个bug,调用labelText()方法需要对象引用。但是Form1不是一个对象,它是一个类型。这在VB.NET中仍然是可能的,这是一个可怕的兼容性攻击。但当您在工作线程中使用它时,它不起作用,您将得到一个新的Form1对象。你看不到它,它也不是你正在看的那个。你需要一个合适的推荐人。谢谢你们的回复。Hans你能澄清一下你的上述评论吗?你说这是vb.net的一个bug,我需要以不同的方式引用我的Form1类?如果是的话,正确的参考方式是什么?我相信我已经尝试过引用:Form1 mainForm作为新Form1。。。仍然没有Luckkalso尝试:Form1 mainForm作为Form1,没有luckHey John工作!!!太感谢你了!!这将在将来为我节省很多时间。我读过类似的解决方案,但没有一个是直截了当的,这样我就能确切地理解发生了什么。再次感谢!我会投赞成票,但我的支持率仍然太低。