如何使用模块从线程更新主窗体创建新的主窗体?

时间:2013-12-31 03:16:44

标签: vb.net multithreading

所以我对模块的使用是这样的,我可以在我为雇主开发的不同程序中使用相同的功能。他们还希望我的模块能够在其他程序员中分发,以便他们也可以使用它。程序需要知道什么时候线程仍在运行(SQL代码正在运行(sql方面没有问题),并且需要在完成所有工作但用户需要能够排队工作时通知用户)

从我使用此代码的主窗体:

Dim thread1 As New System.Threading.Thread(AddressOf ModuleTesting.Testing)
thread1.SetApartmentState(Threading.ApartmentState.STA)
thread1.IsBackground = True
thread1.Name = "ModuleLabelCrossThreading"
thread1.Start()

这是我模块的代码:

Public Sub Testing()   
    Form1.threadsrunning += 1

    Form1.accesscontrolsmoduletesting()

    'THIS IS WHERE THE PROGRAM DOES STUFF ILLUSTRATED BY SLEEPING'
    System.Threading.Thread.Sleep(2000)

    Form1.threadsrunning -= 1

    Form1.accesscontrolsmoduletesting()
end sub

访问主窗体上控件的代码是

Public Sub accesscontrolsmoduletesting()

    If Me.InvokeRequired = True Then
        Me.Invoke(New MethodInvoker(AddressOf accesscontrolsmoduletesting))
    Else

        If threadsrunning > 0 Then
            Label4.Text = threadsrunning & " threads running"
        Else
            Label4.Text = "0 threads running"
        End If
    End If

End Sub

我已经知道问题是新线程正在创建一个新表单。我通过显示表单并等待它来测试它,所以它没有立即处理自己,我看到标签已更新。如何让这个线程更新主窗体,而不是仅创建一个新的主窗体,然后在线程死后自行处理?

1 个答案:

答案 0 :(得分:3)

要重申我的注释,您需要获取正在显示的实际Form1,您应该更改您的测试方法以接受Form1的参数,然后您可以使用参数化Thread.Start传入调用表单。正如汉斯所说的那样,你正在遇到一个留在原地以安抚Vb6 programmers transitioning to VB.net的功能。你可能会发现这个Blog Post by John Mcllhinney an interesting read

来自Second Link(强调我的):

  

要从辅助线程访问表单,通常需要测试其InvokeRequired属性,然后调用其Invoke方法。我前面说过,只有一个表单类的默认实例。这并非严格意义上的。实际上,默认实例是特定于线程的,因此每个线程只有一个默认实例。因此,如果您测试默认实例的InvokeRequired属性,您将始终访问当前线程的默认实例,而不是主线程上显示的实例。

因此,为了回应上述情况,我会将您的模块测试方法更改为:

Public Sub Testing(myForm As Form1)
    myForm.threadsrunning += 1

    myForm.accesscontrolsmoduletesting()

    'THIS IS WHERE THE PROGRAM DOES STUFF ILLUSTRATED BY SLEEPING'
    System.Threading.Thread.Sleep(2000)

    myForm.threadsrunning -= 1

    myForm.accesscontrolsmoduletesting()
End Sub

我会将Form1的Thread Start Code改为这样。

Dim thread1 As New System.Threading.Thread(AddressOf ModuleTesting.Testing)
thread1.SetApartmentState(Threading.ApartmentState.STA)
thread1.IsBackground = True
thread1.Name = "ModuleLabelCrossThreading"
thread1.Start(Me) 'Note the passing in the instance of the calling Form

进行这些更改后,您的代码就可以正常工作