如何异步创建MDI子窗体?

时间:2014-01-31 23:01:57

标签: vb.net

我有父VB.Net表单,必须创建一些MDI孩子。

每个MDI必须连接到数据库才能完成一些可能需要一些时间的人员......

我正在尝试使用以下代码异步创建MDI子代,但它仍然是同步执行的:

ParentForm.BeginInvoke(Sub() 
                       CreateMDIChildForm()
                       End sub)

此代码执行但它仍然是同步的,并且父窗体冻结。

我尝试在单独的线程中创建MDI,但后来我无法将创建的表单加入到父表单中。

有人有想法吗?

感谢。

3 个答案:

答案 0 :(得分:0)

我可以使用以下代码重现这一点:

Public Class Form1

    Private Sub Open(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Me.BeginInvoke(Sub() Me.CreateMDIChildForm())
    End Sub

    Private Sub CreateMDIChildForm()
        Dim f As New Form2()
        MsgBox("OK")
    End Sub

    Public Class Form2
        Inherits Form
        Sub New()
            Thread.Sleep(5000)
        End Sub
    End Class

End Class

修复将是这样的:

Public Class Form1

    Private Sub Open(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        If (Me.operationCompleted Is Nothing) Then
            Me.operationCompleted = New SendOrPostCallback(AddressOf Me.CreateMDIChildFormCompleted)
        End If
        Me.asyncOperation = AsyncOperationManager.CreateOperation(Nothing)
        Dim thread As New Thread(AddressOf Me.CreateMDIChildForm)
        thread.Start()
    End Sub

    Private Sub CreateMDIChildForm()
        Dim f As New Form2()
        Me.asyncOperation.PostOperationCompleted(Me.operationCompleted, f)
    End Sub

    Private Sub CreateMDIChildFormCompleted(args As Object)
        Dim f As Form = DirectCast(args, Form)
        'TODO: Set mdi child, show window etc.
        MsgBox("OK")
    End Sub

    Private asyncOperation As AsyncOperation
    Private operationCompleted As SendOrPostCallback

    Public Class Form2
        Inherits Form
        Sub New()
            Thread.Sleep(5000)
        End Sub
    End Class

End Class

答案 1 :(得分:0)

修复此类问题的推荐方法是 not 尝试在单独的线程中加载表单,而是仅在单独的线程中执行耗时的工作。

在这种情况下,这意味着您将正常加载MDI子表单,所有表单都在同一个UI线程上,但在子表单中,它们每个都会启动一个单独的线程来执行与DB相关的工作,这是导致挂断。这样,数据库内容不会导致表单加载挂起。表单将加载并快速显示,然后数据库工作将在表单可见后完成。

您可能需要禁用子窗体上的部分或全部控件,直到数据库工作完成为止。您可能还希望子窗体显示某种旋转动画以显示它仍在加载。在UI中实现单独线程的最简单方法是使用BackgroundWorker组件。您可以在表单设计器工具框的“组件”部分找到它。

答案 2 :(得分:0)

解决方案:

Dim Thread as new Thread(sub()
                               ParentForm.BeginInvoke(sub()
                                                      CreateMDIChild()
                                                      end sub)
                         end sub)
Thread.Start()

这样,MDI子表单仍然由父表单创建,但所有内容都在一个单独的线程中完成。