私は以下のコードはC++である知っている - 、CLIが、私はDataGridView
で複数の行を「組み合わせる」と思ったとき、それは同じよう避け競合状態
でのC#を指し、私は最初にcreate a custom DataGridViewRow
にしようとしましたが、それはDataGridViewTextBoxCell
よりも他の細胞タイプを実装することはほとんど不可能だったという欠点がありました。
私の次の解決策はカスタムを作成していました。DataGridView
これは本当にうまくいきました。
それは多くの場合、デバッグ中に、時には通常のプログラム実行中に、私はDataGridViewのか、部品を描画するために呼び出された内部.NETコードの異なる場所から例外を取得する機能
OnCellFormatting()
OnCellPainting()
OnRowsRemoved()
OnSelectionChanged()
問題があるが、上書きされますそれの。例:
Stack Trace:
bei System.Windows.Forms.DataGridViewTextBoxCell.PaintPrivate(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, Int32 rowIndex, DataGridViewElementStates cellState, Object formattedValue, String errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts, Boolean computeContentBounds, Boolean computeErrorIconBounds, Boolean paint)
bei System.Windows.Forms.DataGridViewTextBoxCell.Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, Int32 rowIndex, DataGridViewElementStates cellState, Object value, Object formattedValue, String errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
bei System.Windows.Forms.DataGridViewCell.PaintWork(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, Int32 rowIndex, DataGridViewElementStates cellState, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
bei System.Windows.Forms.DataGridViewRow.PaintCells(Graphics graphics, Rectangle clipBounds, Rectangle rowBounds, Int32 rowIndex, DataGridViewElementStates rowState, Boolean isFirstDisplayedRow, Boolean isLastVisibleRow, DataGridViewPaintParts paintParts)
bei System.Windows.Forms.DataGridViewRow.Paint(Graphics graphics, Rectangle clipBounds, Rectangle rowBounds, Int32 rowIndex, DataGridViewElementStates rowState, Boolean isFirstDisplayedRow, Boolean isLastVisibleRow)
bei System.Windows.Forms.DataGridView.PaintRows(Graphics g, Rectangle boundingRect, Rectangle clipRect, Boolean singleHorizontalBorderAdded)
bei System.Windows.Forms.DataGridView.PaintGrid(Graphics g, Rectangle gridBounds, Rectangle clipRect, Boolean singleVerticalBorderAdded, Boolean singleHorizontalBorderAdded)
bei System.Windows.Forms.DataGridView.OnPaint(PaintEventArgs e)
bei System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
bei System.Windows.Forms.Control.WmPaint(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.DataGridView.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
これは、UI以外のスレッドの内部から複数の行を一度に削除することによって発生します。実際には、それらを一度に削除すると良いと私の問題を解決するだろうが、イベントはすべての行の削除後に呼び出されるので、それは不可能です。 :-(
例外が、もちろん、動作しないことができ、塗装されている間、行が削除された場合。これは常にただ時々なく起こるので、それは間違いなく削除とpaiting間の競合状態だ発生します。
私の質問:私はそれを引き起こしたコードへのアクセス権を持っていないので、どのように私はその競合状態を避けることができ、私がこれまで行ってきた
何?:複数行の削除を開始する前に、私はで
m_bUpdateControl = true
を設定しましたすべての4つのオーバーライドされた関数、私は
if (m_bUpdateControl)
return;
しかし、まだ解決していません。私は次のやっていること
:私はOnCellPainting()
に
if (m_bUpdateControl) { i_oEventArgs->FormattingApplied = true; return; }
を使用OnCellFormatting()
で
は、私が使用し
if (m_bUpdateControl) { i_oEventArgs->Handled = true; return; }
しかしこれでもまだ十分ではありません安全に競合状態を避けてください。
他に何ができますか?
これは通常のDGVでも発生しますか?
残っている唯一のアイデアは、UIスレッドで行削除の関数を呼び出すことです。そのため、DGV上で動作するスレッドは1つだけで、競合状態はうまくいきません。
編集:私は定期的にDGVでテストされ、非UIスレッドから行を削除するときは常にInvalidOperationException
を持っている
。もちろん、UIオブジェクトに対するクロススレッド操作は不可能なので、これは意味をなさない。だから私はなぜ私のアプリケーションで可能だったのだろうかと思った。
私は小さなテストプロジェクトを作成し、最終的にその理由を見つけました。メインアプリケーションはDLLを実装しています。ベンダーは、電話で私に言ったように、このDLLのメインクラスの初期化ルーチンは、その後のクロススレッド操作を可能にします
Control.CheckForIllegalCrossThreadCalls = false;
を呼び出します。したがって、このチェックが無効にされていない場合は、UIスレッドで行削除を強制することになりましたが、初期の問題を回避する可能性が最も高いです。