0

.NET 4.0 では、読み込み時間が長い (約 20 秒) アプリを扱っているため、読み込み中にアプリケーションの上に来るフォームにスウィッシュ スクロール マーキーを表示したいと考えていました。

メインの UI スレッドがすべてのデータ UI 要素の読み込みを行っているため、それを別のスレッドで実行することができなかったため、新しいスレッドでフォームを実行しようとしました。このコードをフォーム自体に貼り付けて、次のように新しいスレッドに表示することになりました。

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

これはおそらく非常に不器用ですが、アプリケーションのさまざまな場所で表示しているので、これが最もコード効率の良い方法のように思えました...

実際には非常にうまく機能しますが、これで時々問題に遭遇し、これらの問題に対処する方法について助けが必要です.

  • フォームが閉じられると、スレッドが安全でない方法で中止されているというエラーが表示されることがあります。

  • 現時点では、フォームをフォームの中央に手動で配置して、フォームをカバーしたいと考えています。理想的には、それを呼び出すことができるようにしたい.ShowDialog(ParentForm)のですが、もちろん、あるフォームから別のフォームへのクロススレッド アクセスのために例外が発生します。

これを解決する方法についての提案は大歓迎です。私はスレッド化についてほとんど何も知らないので、おそらくこれを猿のようにコーディングしたので、これを行うためのより良い方法があれば、それについて知りたいと思っています.

私がリストしたコードは VB.NET にありますが、C# の回答コードも問題ありません (熱狂的なリガーのために)

アップデート:

質問でもっと多くの詳細を提供する必要があったことに気づきました...待機フォームは、実際にはアプリを表示する最初のフォームではありません。まずはログイン画面です。ユーザーが認証されると、ログイン フォームはアプリのメイン インターフェイスを起動しますが、これは実際には読み込みに時間がかかるフォームです。

ログイン フォームとメイン インターフェイスの間に待機フォームを表示しています。また、このフォームを使用して、ユーザーがメイン インターフェイスで起動した実行時間の長いタスクをカバーします。

4

4 に答える 4

1

VisualStudio でこれを行うことができます。もちろん、自分で作成することもできますが、プロジェクトのオプションを見るApplicationと、 の設定がありますSplash Screen。任意のフォーム (スタートアップ フォーム以外) をスプラッシュ スクリーンに割り当てることができます。これは独自のスレッドで実行され、起動時に呼び出しをマーシャリングして進行状況バーなどを進めることができます。

MSDN : スプラッシュ スクリーン

于 2013-03-22T10:30:01.580 に答える
1

別のスレッドでダイアログを表示しようとする代わりに、読み込みコードを別のスレッド/バックグラウンド ワーカーに移動する必要があります。

次に、スレッドを開始し、form_load で進行状況バーを表示し、スレッドが完了すると進行状況バーを非表示にします。

Dim _progressForm As frmLoading

    Private Sub frmMain_Load(sender As System.Object, e As System.EventArgs) Handles Me.Load
        'start loading on a separate thread
        BackgroundWorker1.RunWorkerAsync()
        'show a marquee animation while loading
        _progressForm = New frmLoading
        _progressForm.ShowDialog(Me)
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        'simulate a long load
        For i As Integer = 1 To 10
            System.Threading.Thread.Sleep(1000)
        Next
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        _progressForm.Close()
    End Sub
于 2013-03-22T10:03:02.797 に答える
0

TaskFactory.New を見てください。

別のスレッドのスレッド化されたコードを実行して、UI の応答性を維持します

http://msdn.microsoft.com/en-us/library/ee782519.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-3

于 2013-03-22T11:01:38.130 に答える