【问题标题】:How to open VB.Net dialog window on top of form window that is opening the dialog?如何在打开对话框的表单窗口顶部打开 VB.Net 对话框窗口?
【发布时间】:2023-03-30 21:33:01
【问题描述】:

在我的 Form1 类中,我有一个名为 beginProcessingItems() 的方法,它对项目列表进行操作。这个列表可能非常大,所以我在一个新线程中执行 beginProcessingItems 方法,如下所示:

Dim processThread As New Thread(AddressOf beginProcessingItems)
processThread.Start()

有时我需要显示一个对话框来从用户那里收集有关某个项目的其他信息。此对话框是在 beginProcessingItems() 方法中创建和打开的,该方法现在在与我的 Form1 窗口不同的线程中运行。

当我打开对话框时,它正在 Form1 窗口后面加载。我在其他堆栈帖子中尝试了各种建议,但最终都导致跨线程操作无效异常。

这是我当前必须打开对话框的代码:

Public Sub beginProcessingItems()  
    ' ..do stuff .. and sometimes:
    Dim IDD As New ItemDetailsDialog()
    IDD.Location = ImportItemsButton.Location ' sets X,Y coords
    IDD.StartPosition = FormStartPosition.Manual
    IDD.TopMost = True
    'Note: Me = The Form1 object
    'IDD.Parent = Me '<-- also throws exception.
    If IDD.ShowDialog(Me) = DialogResult.OK Then ' <-- If I remove "Me" then the dialog opens but its underneath the Form1 window.
       ' .. do stuff with the dialog results
    End If
End Sub

这是异常消息:

跨线程操作无效:控件“Form1”从 线程不是创建它的线程。

【问题讨论】:

  • 是的,一旦您开始尝试进行任何类型的 UI 交互,您就会 100% 遇到后台线程问题。您确实需要通过您的收集所有要求并将其传递到线程中。或者,也许迁移到更新的 Async/Await 模式可能会简化您的 UI 要求

标签: .net vb.net multithreading winforms dialog


【解决方案1】:

我能够将代码放入使用委托的工作中。

在 Form1 类中,我添加了:

' = Created a public property to hold the dialog object ======
Public IDD As ItemDetailDialog = Nothing

' = Created a Delegate ======
Delegate Sub DelegateShowItemDetailDialog(ByVal Param1 As Integer, ByRef SomeClassObj As SomeClass, ByVal Param3 As Integer)

' = Created a method that instantiates the IDD  property and shows the dialog =====
Private Sub ShowItemDetailDialog(ByVal Param1 As Integer, ByRef SomeClassObj As SomeClass, ByVal Param3 As Integer)
    IDD = New ItemDetailDialog(Param1, SomeClassObj, Param3)
    IDD.Location = ImportItemsButton.Location ' sets X,Y coords
    IDD.StartPosition = FormStartPosition.Manual
    'IDD.TopMost = True ' <-- not needed
    'IDD.Parent = Me ' <-- not needed
    IDD.ShowDialog()        
End Sub

' = Instantiate the Delegate object into a public property 
' = that will get invoked from the beginProcessingItems() method running in a separate thread
Public ThreadShowItemDetailDialog As New  DelegateShowItemDetailDialog(AddressOf ShowItemDetailDialog)

我修改了 beginProcessingItems 方法如下:

Public Sub beginProcessingItems()  
    ' ..do stuff .. and sometimes:
    Me.Invoke(ThreadShowItemDetailsDialog, {Param1, SomeClassObj, Param3})
    ' dialog is now on top of the form1 window :-)
    If IDD.DialogResult = DialogResult.OK Then
       ' .. do stuff with the dialog results via the IDD class object
    End If
End Sub

请注意,Param1、SomeClassObj 和 Param3 变量显示为如何将参数值传递给对话框对象的示例。显然,您可以将它们更改为您的对话框对象实例化器所需的任何内容。

【讨论】:

    【解决方案2】:

    尝试将其放入您的 Sub Form_Load:

    CheckForIllegalCrossThreadCalls = False
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多