无法从另一个线程中隐藏表单

Impossible to hide a Form from another Thread

提问人:ezio 提问时间:12/22/2022 最后编辑:ezio 更新时间:12/22/2022 访问量:46

问:

我尝试过使用窗体或控件,但没有任何效果。

主线程上的两个表单(FrmMain 和 FrmWait)和另一个长工作线程。

FrmWait 仅显示带有“正在下载”动画 gif 的 PictureBox。我想从线程中隐藏 FrmWait。

在 FrmMain 中

    Private Sub StartThread()
        Debug.Print("Main ThreadId is: " & System.Environment.CurrentManagedThreadId)

        FrmWait.Show()
        Dim trd As New Thread(Sub()
                                  Flag.Agisci(Num, Value1, value2)
                              End Sub)
        trd.Start()
    End Sub

    Private Sub FrmMain_HandleCreated(sender As Object, e As EventArgs) Handles Me.HandleCreated
        Debug.Print("FrmMain Handle has been created: " & Me.Handle.ToString)
    End Sub

在 FrmWait 中

   Private Delegate Sub CloseForm(hide As Boolean)
  
   Public Sub CloseWait(hide As Boolean)
        Debug.Print("******************* Entring in CloseWait")
        Try
            Dim h As IntPtr = Me.Handle
            Debug.Print("................... InvokeRequired is: " & Me.InvokeRequired.ToString & " on Handle: " & h.ToString)
            If Me.InvokeRequired Then
                Debug.Print("----------- Invoke is Required !!")
                Me.Invoke(New CloseForm(AddressOf CloseWait), hide)
            Else
                Debug.Print("+++++++++++ Calling Me.Visible = " & hide.ToString)
                Me.Visible = hide
            End If
        Catch ex As Exception
            Debug.Print(ex.ToString)
        End Try
    End Sub

    Private Sub FrmWait_HandleCreated(sender As Object, e As EventArgs) Handles Me.HandleCreated
        Debug.Print("FrmWait Handle has been created: : " & Me.Handle.ToString)
    End Sub

在 Thread 类中:

    Public Sub Agisci(Num As Integer, Value1 As String, Value2 As String)
        Try
            Debug.Print("Task ThreadId is: " & System.Environment.CurrentManagedThreadId)
            Sleep(2000)
            Throw New Exception("Foo")
      
            'some stuff bypassed by the exception

        Catch ex As Exception
            Debug.Print(ex.Message)

            FrmWait.CloseWait(True)

            'this is another Form that is correctly displayed
            FrmMessBox.SetText(ex.Message)
            FrmMessBox.ShowDialog()
        End Try
    End Sub

输出:

FrmMain 句柄已创建: 4785876
Main ThreadId 为: 1 FrmWait 句柄已创建: 655546
任务 ThreadId 为: 5
Eccezione generata: 'System.Exception' in MyApp.exe -Foo
---------- Entring in CloseWait
FrmWait
Handle has been created: 917984
----------- InvokeRequired is: False on Handle: 917984 '****** FALSE?????
+++++++++++ Calling Me.Visible = False '************* 不起作用!

vb.net 多线程

评论

1赞 Hans Passant 12/22/2022
这是 VB.NET 程序中一个臭名昭著的错误,当从工作线程调用时,FrmWait.CloseWait() 将创建一个表单。它不可见,它的 Show() 方法没有被调用。使用关键字创建可在两个线程上使用的 FrmWait 实例。New
0赞 Hans Passant 12/22/2022
请注意,您实际上可以看到创建了两个 FrmWait 实例,“FrmWait 句柄已创建”出现两次。第二个是麻烦制造者。
0赞 jmcilhinney 12/22/2022
您使用的是默认实例,并且它们是特定于线程的。点击此处了解详情。

答:

0赞 ezio 12/22/2022 #1

根据汉斯·帕桑特(Hans Passant)的回答,我在模块中声明:

    Public FrmWait2 As New FrmWait

我在代码中将 FrmWait 更改为 FrmWait2。现在调试报告:

---------- Entring in CloseWait
++++++++++++ Invoke is required !!'是的,现在另一个线程是可见
的 ---------- Entring in CloseWait
++++++++++++ Calling Me.Visible = False

代码

    Debug.Print("------------ InvokeRequired is: " & 
              Me.InvokeRequired.ToString & " on Handle: " & Me.Handle.ToString)

以前

    If Me.InvokeRequired Then.......

生成“System.InvalidOperationException'”,用于从其他线程调用。:)

为什么我必须以这种荒谬的方式纠正代码才能工作,这是一个真正的迷雾。