2

イベントをログに記録するためのクラスを作成しています。私の LogClass はシングルトンとして実装されており、システム内のどのクラスでもログ エントリを書き込むことができます。エントリはリストに保存され、バッファがいっぱいになるとディスクにダンプされます。

実行中に LogClass の内容を表示するために DataGridView を使用しているため、BindingList を使用して Viewer が自動的に更新されるようにしました。

私のクラスがどれほどスレッドセーフなのか疑問に思っています。リストに新しいエントリを追加するたびに「ロック」を使用しています。また、リストを繰り返し処理してディスクにダンプするときも使用しています。DataGridView 以外に、ログから読み取るオプションがなく、エントリをログに追加するためのオプションがないため、このクラスは基本的に書き込み専用です。ダンプは内部で実行され、BindingList に明示的な読み取りコマンドがあるのはそのときだけです。

だから私の本当の懸念は、 DataGridView と BindingList で何が起こっているのですか? BindingList は、リストが変更されるたびにイベントをスローします。追加が完了するとイベントがスローされるため、新しいエントリを追加する場合、これは問題ではないようです。

Dump() の私のコードは次のとおりです。

lock (lockObj) {
    foreach (LogEntry le in List) {
      writeToDisk(le)
      removeFromList(le)
    }
 }

繰り返し全体でリストをロックしているにもかかわらず、イベントがビューアーにスローされ、リストが変更された (削除のため) ため、DataGridView によって読み取られます。リストを変更している間、リストへの読み取り/書き込みは本当に必要ありません。何か案は?

4

2 に答える 2

1

一度バインドすると、(Control.Invoke から継承された) Form.Invoke メソッドからしかリストを変更できないため、実際には問題になりません。別のスレッドからリストを変更しようとすると、.NET ランタイムは、「現在のスレッドからこのリストを変更することはできません」という趣旨の何かを示す例外を伴って吠えます。

これには、取得できるコードがいくつかあります。

よろしく、 =アラン

于 2009-10-28T21:03:33.443 に答える
1

BindingList は変更通知を実装していないと思いました。このシナリオでは、これはスレッドセーフではないと思います。

解決策は、IBindingList を実装するカスタム コレクションを使用し、要素を返す前にロックを取得するようにリスト アクセサーを変更することです。

私は変更通知を伴う IBindingList のカスタム実装を持っているので、必要に応じてこれを共有できます。

于 2009-10-24T14:10:47.347 に答える