2009-04-01 8 views
1

私のアプリケーションにはPropertyGridがあり、これは任意のオブジェクトの編集に使用されています。私はこれらのオブジェクト(検索機能、あなたが好奇心が強い場合)を見る別のスレッドで任意のサブルーチンを実行できる必要があります。明白な問題は、ユーザーがこれらのオブジェクトの1つを、検索スレッドが読み取っているときに同時に編集している可能性があります。これは避ける方が望ましいでしょう(ただし、検索スレッドが読んでいるだけなので、書きません)。 lock(obj)を呼び出す.Net PropertyGridスレッドセーフ

は私の検索スレッドから十分に簡単ですが、リフレクターでPropertyDescriptorGridEntryのコードを文書化し、簡単にスキムミルクを見た後、私は上の問題のオブジェクトにSystem.Threading.Monitor.Enter()/Exit()コールを使用する類似点を見つけるように見えることはできませんPropertyGrid。私はBeginEditイベントとEndEditイベントがあり、これを簡単にすることができればと思っていましたが、そのようなことは見つけられません。オブジェクト全体がロックされていないのは、PropertyGridに表示されている間にオブジェクト全体をロックしたくないからです。別のオブジェクトが選択されるまで、検索スレッドをブロックすることになります。

私はWindowsフォームのスレッドモデルに少し新しかったので、私は見落としてしまった明らかな答えがあることを期待しています。どんな助け?

編集:が同期非同期検索を実行する前に、私のオブジェクトを複製するには、おそらく私も同期の検索自体を実行する可能性があることを十分に非効率的になります - 非同期で実行されているのポイントはもちろんである私のユーザーがしばらく作業を継続できるようにします検索が実行されています。私が行っているデータセットは最終的には任意の大きさになるため、同期クローニングは避けようとしているユーザビリティの問題を引き起こすように見えるため、検索のスケールが必要です。

答えて

0

私はあなたがこれについてかなりの仕事をしなければならないと思います。

まず、ICustomTypeDescriptorの実装を作成する必要があります。この実装は、通常、そのタイプのTypeDescriptorに実装されます。

次に、ロックしたいメンバのディスクリプタを公開するメソッドの実装では、ディスクリプタから派生したサブクラスを提供し、ロックをラップするための適切なメソッドをオーバーライドします。

プロパティの場合、PropertyDescriptorの特定のサブクラスを返すようにGetPropertiesを実装します。これらのサブクラスは、GetValueおよびSetValueメソッド(およびその他)をオーバーライドし、これらの変数にアクセスするときにロックを使用します。

UIスレッドでこれをロックすることは、そのスレッドの操作を任意にブロックしたくないため、おそらく悪い考えです。オブジェクトのクローンを作成し、完了したらオブジェクトのストアを更新するメソッドを用意するほうが良いかもしれません。

+0

を台無しにしてしまう同期クローニング、 PropertyGridの場合、PropertyTabをサブクラス化してGetPropertiesをオーバーライドすることで、より簡単に行うことができます。仕事はまだ**たくさんありますが、実際にはICustomTypeDescriptor(TypeDescriptionProvider)経由でシムする必要はありません –

+0

@Marc Gravell:You PropertyDescriptorから派生し、GetValueとSetValueをオーバーライドして示したことを行うサブクラスを作成する必要がありますが、これはほぼ同じ量ですが、ICustomTypeDescriptor実装の一般的な使用があります。 – casperOne

+0

しかし、ICustomTypeDescriptorでは、グリッドだけでなく、表示されているタイプを制御する必要があります。 –

0

スレッドセーフではありません。あなたは、UIスレッドに検索コードのビットをマーシャリングすることができますが、それは物事を遅くし、おそらくスレッドのポイントを倒す...

検索はどのくらい速くする必要がありますか?クローンと対戦できますか?

+0

;) –

+0

編集質問 - そうなスレッドの目的を台無しにしてしまう:(同期クローニング –

0

データを表示する前にクローンを作成して、クローンで検索スレッドを稼働させることはできますか?検索スレッドに変更が反映されるようにするには、PropertyGridのイベントに応答し、おそらくに変更してください。しかし、単に「古くなった」データを使用する方が簡単かもしれません。

データの複製は非常に効率的ではありませんが、各スレッドが完全に独立したデータを扱う(またはすべてのスレッドのみを読み取る)場合は、

+0

編集質問 - おそらく実際には、スレッドの目的:( –

0

私は間違っている可能性がありますが、間違ったところから来ているようです。

解決すべき2つの明確な問題があります。

最初に、PropertyGridがUIスレッドでのみアクセスされていることを確認します。そのメソッドのうちのどれか(プロパティ取得/設定を含む)が他のスレッドからアクセスされると、不思議な方法で苦痛を受けます。もちろん、例外はInvokeRequired()Invokeです。

第2に、検索スレッドが正しく実行できることを確認します。

最初の問題を解決するために、どちらかは、あなたのオブジェクトは、UIスレッドで以外を修正されることはありませんことを確認し、またははあなたのイベントのすべてが(そのようにPropertyChangedなど)あなたのオブジェクトのイベントがあるように注意してくださいスレッドトリガー作りますUIスレッドでのみ起動されます。

2番目の問題は簡単です。検索スレッドがコアオブジェクトからのみ読み込みを行う限り、すべて正常に動作するはずです。はい、検索スレッドで誤って部分的に更新されたデータが表示されることがありますが、それは本当に問題ですか?

最終的思考のカップル...

  • PropertyGridの自体を反復処理するために検索を実装しないでください。前のオブジェクトのリストを取得し(クローンである必要はありません)、代わりにそれを処理します。

  • アイドル処理を使用して検索することを検討しましたか? Applicationオブジェクトは、処理するメッセージがアプリケーションで不足するたびにイベントを発生させます。イベントが発生するたびに、これにフックして1段階の検索を実行できます。一種の貧弱なスレッドがありますが、mutex/lock/semaphoneの頭痛はありません。私はこれを使って過去に非常に良い効果を得ました。

更新:私が正しくリコール場合は、PropertyGridのは、あなたが別の行に移動すると、すぐにあなたが行を変更し始めるとBeginEditを呼び出し、そしてEndEditIEditableObjectインタフェースを尊重します。これを利用して、検索スレッドに不完全な変更が見られないようにすることができます。

アップデート2:フォローアップ、私はあなたが既に知っていたものを発見した - PropertyGridのがIEditableObjectインターフェイスを尊重しないこと。

私は別の提案があります - あなたが投資したい以上の仕事かもしれませんが。

.NET 2.0でSystem.Transactionsネームスペースが導入された頃、アンビエントトランザクションを使用してオブジェクトのスレッド分離を提供する記事がありました。アイデアは、オブジェクトのプロパティにデュアルストレージがあることです。最初にコミットされた値がすべてのスレッドに表示され、コミットされていない値をスレッドごとに格納するためにスレッドローカル変数が使用されます。プロパティが変更されると、オブジェクトはスレッドローカルに新しい値を格納することによって、任意のアンビエントトランザクションで登場する。トランザクションがコミットまたはロールバックされると、スレッドの値は格納されるか破棄されます。

残念ながら、元の記事は見つかりませんが、CSLAはこのサポートを提供しているようです。お役に立てれば。

私は詳細に行っているべきではありません知っていた
+0

"あなたの検索スレッドは誤って部分的に更新されたデータを見るかもしれません"と私が懸念している、避けたいと思う*唯一の*問題です。他に何も問題はない(私は自分がやっていることを知っている...ほとんど)。私のアプリがそれほど重労働でないなら、アイドル処理がうまくいったかもしれません。 –

+0

私は正しくリコールしているとは思わない - あなたのリンクと私のメモリの両方が、BeginEditとEndEditを持つIEditableObjectがPropertyGridではなくDataGridViewで使用されていることを示している。 –

関連する問題