在等待主 UI 线程完成的单独线程上运行表单 [英] Running a form on a separate thread waiting for main UI thread to complete

查看:30
本文介绍了在等待主 UI 线程完成的单独线程上运行表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 .NET 4.0 中,我正在处理一个加载时间很长(大约 20 秒)的应用程序,所以我想在加载时在应用程序顶部的窗体上显示一个漂亮的滚动字幕.

In .NET 4.0 I'm dealing with an app which has a long loading time (about 20 seconds), so I wanted to display a swish scrolling marquee on a form that comes on top of the application whilst it is loading.

由于主 UI 线程正在执行所有数据 UI 元素的加载,因此我无法在单独的线程上执行该任务,因此我最终尝试在新线程上运行该表单.我最终将这段代码粘贴在表单本身中,让它在一个新线程中显示出来,如下所示:

Since the main UI thread is doing all the loading of data UI elements, I couldn't get that to execute on a separate thread, so I ended up trying to run the form on a new thread. I ended up sticking this code in the form itself, to have it show itself on a new thread, like this:

Public Class frmWait

Public Property Message As String
    Get
        Return Me.lblMessage.Text
    End Get
    Set(value As String)
        If Not String.IsNullOrEmpty(value) Then
            Me.lblMessage.Text = value
        Else
            Me.lblMessage.Text = DefaultMessage
        End If
    End Set
End Property

Private OwnerThread As Thread
Private OwnerForm As Form
Private Const DefaultMessage As String = "しばらくお待ちください..."

Public Sub New(ByVal ParentForm As Form)

    InitializeComponent()

    Me.Message = DefaultMessage
    Me.OwnerForm = ParentForm

End Sub

Public Sub New(ByVal Message As String, ByVal ParentForm As Form)

    Call InitializeComponent()

    Me.Message = Message
    Me.OwnerForm = ParentForm

End Sub

Public Sub ShowOnThread()

    ' Position the form in the center of the owner
    With Me.OwnerForm
        Dim ownerCenter As New Point(.Location.X + CInt(.Width / 2), .Location.Y + CInt(.Height / 2))
        Me.Location = New Point(ownerCenter.X - CInt(Me.Width / 2), ownerCenter.Y - CInt(Me.Height / 2))
    End With

    Me.OwnerThread = New Thread(New ThreadStart(AddressOf Me.ShowDialog))
    Call Me.OwnerThread.Start()

End Sub

Public Shadows Sub Close()

    If Me.OwnerThread IsNot Nothing AndAlso Me.OwnerThread.IsAlive Then
        Call Me.OwnerThread.Abort()
    Else
        Call MyBase.Close()
    End If

End Sub

End Class

这可能很笨拙,但我在应用程序的不同地方展示了它,所以这似乎是最高效的代码方式...

This is probably quite clumsy, but I am showing it in different places in the application, so this seemed the most code-efficient way of doing this...

它实际上工作得很好,但我不时遇到问题,需要一些帮助来解决这些问题.

It actually works quite well, but I am encountering problems from time to time with this and need some help on how to address these issues.

  • 有时当表单关闭时,我会收到有关线程以不安全方式中止的错误.

  • Sometimes when the form gets closed I get an error about the thread being aborted in an unsafe manner.

目前我手动将表单放置在表单的中心,我希望它覆盖表单.理想情况下,我希望能够对其调用 .ShowDialog(ParentForm) ,但当然这会引发异常,因为从一种形式到另一种形式的跨线程访问.

At the moment I position the form manually in the centre of the form I want it to cover form. Ideally I'd like to be able to call .ShowDialog(ParentForm) on it, but of course that raises an exception because of cross-thread access from one form to the other.

任何有关如何解决此问题的建议将不胜感激.因为我对线程几乎一无所知,所以我可能像猴子一样编码,所以如果有更好的方法来完成这项工作,我非常想知道.

Any suggestions on how to resolve this would be most appreciated. Because I know virtually nothing about threading I probably coded this like a monkey, so if there is a better method to get this done, I would very much like to know about it.

我列出的代码是在 VB.NET 中,但在 C# 中的回答代码也很好(对于任何过分热心的 retaggers)

The code I list is in VB.NET, but answer code in C# is fine too (for any overzealous retaggers)

更新:

我现在意识到我应该在我的问题中提供更多详细信息...等待表单实际上不是我显示应用程序的第一个表单.首先是登录屏幕.当用户通过身份验证时,登录表单会启动应用程序的主界面,该表单实际上需要很长时间才能加载.

I realise now that I should have given a lot more details in my question... The wait form is actually not the first form I am displaying the app. There first is a login screen. When the user is authenticated, the login form launches the main interface of the app, which is the form which actually takes a long time to load.

我在登录表单和主界面之间显示等待表单.我还使用此表单来涵盖用户在主界面上启动的任何长时间运行的任务.

I am displaying the wait form in between the login form and the main interface. I also use this form to cover for any long running tasks launched on the main interface by the user.

推荐答案

VisualStudio 可以为您做到这一点.当然,您当然可以自己编写,但是如果您查看 Application 下的项目选项,就会有 Splash Screen 的设置.您可以将任何表单(启动表单除外)指定为启动画面.这在它自己的线程上运行,您可以在启动期间编组调用它以推进进度条等.

VisualStudio can do this for you. You can certainly write your own, of course, but if you look at your project options under Application there is a setting for Splash Screen. You can assign any form (other than the startup form) to be your splash screen. This runs on its own thread and you can marshall calls to it during startup to advance a progress bar, etc.

MSDN:启动画面

这篇关于在等待主 UI 线程完成的单独线程上运行表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆