0

私の winforms アプリケーションは、ハードウェア デバイスと対話する必要があります。表示は一種のワークフローです...ステップ1の後..完了..ステップ2に進みます..など.表示は動的で、実行時にコントロールが表示され、アクティビティが開始されます(これらの各ユーザーコントロールはタイマーを使用します/内の BGWorker)。

timer/BGWorker_Completed からカスタム イベントを発生させています。これは、次のステップに進み、UI を更新するのに役立ちます。私は正しいことをしていますか?

私はwinformsの初心者で、ディスプレイが失敗する理由を理解できません。

私は例外をキャッチしていません...しかし、特定のステップの後、コントロールが表示されません!!! このシナリオをデバッグする場所と方法がわかりません。メインフォームをスタンドアローンで実行すると・・・表示も見えます。ただし、ログインページからナビゲートしたり、メインフォーム内のタブを変更して戻ったりすると、表示が表示されません。

UIで更新を呼び出す前に、以下と同じ順序でチェックを入れてみました。Thread.Current.IsBackground が false を返すか、control.IsHandleCreated が true を返すか、dim x=Control.handle()) Me.InvokeRequired/ Control.invokeRequired が false を返します (私が望んでいた方法)。ただし、userControlが表示されていません...可視性/色/すべてが(プログラムで)設定されています..そして、ハードウェアの相互作用を見ることができます!!!..しかし、表示されません:-((ステップ4以降) )

ログインページやtabChangedイベントでは何もしていません。(タブが変更されたイベントで...私は開いている接続をクリーンアップする/ bgワーカーを閉じるだけです..必要なときにいつでも接続されます)

私が何かをする必要があるかどうか教えてください...そしてこの問題を解決する方法. また、すべてのユーザー コントロール/メイン フォームのコンポーネントを初期化した直後に、EnsureHandleIsCreated(control) サブルーチンを呼び出しています。

'Code in Login Form
    Dim myForm as new MainForm()
    myForm.ShowDialog(Me) ' here i also tried with show/showDialog.. with/without ownerForm 
    Me.Hide() ' Hide login page

'Code for checking if handle is created or not
    Public Sub CheckForInvalidThread()
        frmMain.CheckForIllegalCrossThreadCalls() = True
        If Thread.CurrentThread.IsBackground Or Not Thread.CurrentThread.Name Is THREAD_MAIN_NAME Then
            Throw New InvalidOperationException(THREAD_IS_INVALID)
        End If
        If Not Me.IsHandleCreated Then
            Dim x = Me.Handle()
            Thread.Sleep(20)
        End If
    End Sub

    Public Sub EnsureHandleIsCreated(ByRef c As Control)
        Try
            If Not c.IsHandleCreated Then
                Dim h As System.IntPtr = c.Handle()
            End If
        If c.HasChildren Then
                For Each child As Control In c.Controls
                    Try
                        EnsureHandleIsCreated(child)
                    Catch ex As Exception
                        DAL.LogException(ex.Message, ex.StackTrace, "EnsureHandleIsCreated: " & c.Name, 0)
                    End Try

                Next
            End If
        Catch ex As Exception
            DAL.LogException(ex.Message, ex.StackTrace, "EnsureHandleIsCreated: " & c.Name, 0)
        End Try
    End Sub 

    Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        lbRole.Text = RoleName
        lbName.Text = UserName
        Try
            Me.Activate()

            If Thread.CurrentThread.IsBackground Then
                Throw New ApplicationException(THREAD_IS_INVALID)
            End If
            Thread.CurrentThread.Name = THREAD_MAIN_NAME

            CheckForInvalidThread()
            clGlobals.frmMain = Me

            If RoleName Is Nothing Or String.IsNullOrEmpty(RoleName) Or RoleName.Equals("OPERATOR", StringComparison.InvariantCultureIgnoreCase) Then
                tcEtch.TabPages("tbMaintenance").Hide()
                tcEtch.TabPages("tbAdmin").Hide()
            End If
        Catch ex As Exception
             MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    Exit Sub
        Finally

        End Try
        Initiate()
    End Sub 

    Public Sub GoToNextStep() Handles Me.GoToNextStepEvent
        Try
           CheckForInvalidThread()
           CurrentStep = CurrentStep + 1

            Select Case CurrentStep
                Case 0 To 2
                    If Me.InvokeRequired Then
                        _delegateDisplayInitiate = AddressOf DisplayStep2
                        Me.Invoke(_delegateDisplayInitiate)
                    Else
                        DisplayStep2()
                    End If

                Case 3
                    If ucCycleStart.InvokeRequired Then
                        _delegateDisplayInitiate = AddressOf DisplayStep3
                        ucCycleStart.Invoke(_delegateDisplayInitiate)
                    Else
                        DisplayStep3()
                    End If
                Case 4
                    If Me.InvokeRequired Or ucPartCountVerification.InvokeRequired Or Thread.CurrentThread.IsBackground Then
                        Throw New Exception("Check out")
                    End If

                    EnsureHandleIsCreated(ucPartCountVerification)
                    If ucPartCountVerification.InvokeRequired Then
                        _delegateDisplayInitiate = AddressOf DisplayStep4
                        ucPartCountVerification.Invoke(_delegateDisplayInitiate)
                    Else
                        DisplayStep4()
                    End If

             End Select
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub


     Private Sub DisplayStep4() Handles Me.DisplayStep4Event
        ucPartCountVerification.Visible = True
        ucPartCountVerification.Show()
        ucPartCountVerification.Initiate()
    End Sub

     Public Sub Initiate()
            frmMain.CheckForInvalidThread()

            'Just to verify if things are fine.. i put in this check below
        If Me.InvokeRequired Or pnStep4.InvokeRequired Or Not (Me.IsHandleCreated And pnStep4.IsHandleCreated ) Then
                MessageBox.Show("cHECK OUT")
            Else
                Me.Visible = True
                pnStep4.Visible = True

                Me.BackColor = Color.Red
                pnStep4.BackColor = Color.Gray

                Dim height = Me.Size.Height
                Dim width = Me.Size.Width
                MessageBox.Show(height.ToString() + Me.InvokeRequired.ToString())
            End If

    end Sub
4

2 に答える 2

0

あなたは確かにBackgroundWorkerまたはからイベントを発生させることができますTimer。あなたはすでにチェックしていますInvokeRequired、それは正しいことです。次に、UIを更新するために呼び出す必要がありますBeginInvoke(同期が必要な場合は、)。Invoke

于 2012-11-30T15:22:10.773 に答える
0

あなたは正しい方向に進んでいます。一部のライブラリから発生するイベントを処理する場合、それらがどのスレッドで配信されるかを確認することはできません。Windowsフォームには、GUIスレッドからの呼び出し呼び出しが行われるという制限があるため、これは残念なことです。このMSDNの記事では、問題について説明しています。

あなたは正しい方向に進んでいInvokeRequiredます。正しいスレッドにいるかどうかを確認できますが、このケースを処理し、適切なスレッドでイベントを再呼び出しする方法が必要です。

これがC#でこれを行う方法です...

public delegate void uiEventHandler();

void uiEvent(object sender, EventArgs e)
{
    if (InvokeRequired)
    {
        // We are not on the correct thread. We'd better get there.
        var eh = new uiEventHandler(uiEvent);
        Invoke(eh, new object[] { sender, e });
        return; //This thread has no more work to do.
    }

    // Do your work here that requires being performed on the GUI thread.
}
于 2012-11-30T15:22:17.573 に答える