1

私の vb.net 4.0 プロジェクトは社内取引プラットフォームです。

MsgPadと呼ばれる別のフォームには、 MsgPadDGと呼ばれる Datagridview が含まれています。

Form-loadサブは 2 つのことを行います: datagridview をフォーマットし、gridview 更新用のタイマーを定義します。

2 番目の Sub であるUpdateMyMsgは、スレッド化されたUIUpdaterEngineからNewMessageイベントによって更新を受信し、 MyMessagesオブジェクト (基本的にはデータテーブル) を更新します。

3 番目のサブUpdateMdgPadDGW は、invoke メソッドを使用してdatagridviewを更新/更新します (タイマーは UI スレッドで定義されているため、おそらく必要ありません)。

最後に Datagridview のプロパティ: 行はnot user-editableAutoSizeRowsMo​​de = DisplayedcellsおよびScrollBars = Bothとして定義されています。

私の問題は、更新プロセスが datagridview の制限を超えて行を追加すると、アプリ全体がクラッシュし、スクロールバーが表示されることです。タイマーなしで(UpdateMyMsg Subでデータソース更新を直接呼び出す)、タイマーを使用してみましたが、問題は常にあります。奇妙なことに、 Try-Catchブロックは何もキャッチしません。

リプレイをお寄せいただきありがとうございます。

エドアルド

コードは次のとおりです。

Public Class MsgPad
Private WithEvents _MyUIUpdaterEngine As MyUIUpdaterEngine = MyUIUpdaterEngine.Instance
Private MyMessages As New Messages
Private LastUpdate As DateTime = TimeValue("08:00:00")
Private ObjLock As New Object
Private NewMessages As Boolean = False
Dim UpdateDGWTimer As New System.Timers.Timer

 Private Sub MsgPad_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Try
        '--
        MsgPadDG.DataSource = MyMessages.DTable
        '--
        With MsgPadDG
            '--
            .Columns("Msg_ID").Visible = False
            .Columns("I_CommandID").Visible = False
            .Columns("B_ID").Visible = False
            .Columns("F_ID").Visible = False
            .Columns("T_TV").Visible = False
            .Columns("T_Sign").Visible = False
            .Columns("T_Mde").Visible = False
            .Columns("T_QU").Visible = False
            .Columns("T_QI").Visible = False
            .Columns("T_QF").Visible = False
            .Columns("T_PI").Visible = False
            .Columns("T_PF").Visible = False
            '--
            .Columns("Msg_RecDate").HeaderText = "Date"
            .Columns("Msg_RecDate").Width = 50
            .Columns("Msg_RecDate").DefaultCellStyle.Format = "HH:mm:ss"
            .Columns("I_Symbol").HeaderText = "Symbol"
            .Columns("I_Symbol").Width = 80
            .Columns("I_Des").HeaderText = "Des"
            .Columns("I_Des").Width = 180
            .Columns("Msg_Text").HeaderText = "Message"
            .Columns("Msg_Text").Width = 250
            '--

        End With

        '--Crea timer per l'Update del DAtagridView
        AddHandler UpdateDGWTimer.Elapsed, AddressOf UpdateMsgPadDGW
        UpdateDGWTimer.Interval = 3500
        UpdateDGWTimer.Enabled = True
 .....
 .....
 End Sub

 Private Sub UpdateMyMsg(ByVal CRec As OrderRecord, ByVal Msg As String) Handles _MyUIUpdaterEngine.NewMessage

    Try
        SyncLock ObjLock
            '--Aggiorna la tabella MyMessages
            MyMessages.Add(CRec, Msg)
            NewMessages = True
            '--Parla messaggio
            Dim synth As New SpeechSynthesizer
            Dim TalkMsg As String = Msg
            If CRec.I_Des <> Nothing Then TalkMsg += " su: " + CRec.I_Des
            synth.SpeakAsync(TalkMsg)
        End SyncLock
 .....
 .....
 End Sub


 Private Sub UpdateMsgPadDGW(source As Object, e As ElapsedEventArgs)

    '--Aggiorna MesssagePad
    Try
        SyncLock ObjLock
            If NewMessages Then
                MsgPadDG.ControlInvoke(Sub(l)
                                           MsgPadDG.DataSource = MyMessages.DTable
                                           MsgPadDG.Refresh()
                                           MsgPadDG.ClearSelection()
                                       End Sub)
                NewMessages = False
            End If
        End SyncLock
 .....
 .....
 End Sub
4

1 に答える 1

1
        '--Aggiorna la tabella MyMessages
        MyMessages.Add(CRec, Msg)
        NewMessages = True

これは致命的なバグです。DGV は MyMessages にバインドされています。そのため、ワーカー スレッドで Add() を呼び出すと、コントロールが間違ったスレッドから更新されます。通常、間違ったスレッドからコントロールにアクセスすると IllegalOperationException が発生しますが、残念ながらバインドされたデータでは機能しません。

これを別の方法で行う必要があります。代わりに、ワーカーにリストにメッセージを追加してもらいます。次に、呼び出されたコードで MyMessages をこれらの新しいメッセージで更新します。

また、質問で想定したように、タイマーは安全なタイマーではないことに注意してください。System.Windows.Forms.Timer のみが、Tick イベント ハンドラーが UI スレッドで実行される安全なものです。その後、もう呼び出す必要もありません。

于 2012-11-07T14:03:03.753 に答える