2

BindingList にバインドされた DevExpress GridControl があります。

スレッドから BindingList を変更しようとしたところ、例外がスローされました。Google で調べたところ、次の説明が見つかりました。

この問題は XtraGrid とは直接関係ありません。残念ながら、同期で多くの問題が発生するため、バックグラウンド スレッドでグリッドのデータ ソースを変更することはできません。XtraGrid は、バックグラウンド スレッドがデータ ソースを変更すると同時に、基になるデータ ソースに対していくつかの操作を実行する場合があります。この場合、グリッドは後で変更通知を受け取り、データ ソースから行を更新しようとするため、上記の問題が発生します。この問題は、多くの場合に発生する可能性があります。たとえば、ユーザーがデータを編集したり、データをグループ化したり、XtraGrid が集計を再計算しようとしたりする場合です。この問題の唯一の解決策は、バックグラウンド スレッド内でグリッドの DataSource 参照を変更することです (注: Invoke メソッドを使用して実装する必要があります)。別の言い方をすれば、バックグラウンド スレッド内で、DataSource のローカル コピーを操作し、必要に応じてそのクローンをグリッドの DataSource に渡す必要があります。添付の例には、このアプローチを示すサンプル プロジェクトがあります。

私はそれが言ったことを試しました。その結果、次のようになりました。

proxyWorker = new Thread(() =>
{
    //Clone the datasource into the thread
    BindingList<Proxy> newList = new BindingList<Proxy>(proxies);

    //Set the proxy source to the cloned datasource in the thread
    gcProxies.BeginInvoke(new MethodInvoker(delegate { gcProxies.DataSource = newList; }));

   //Logic here
});

proxyWorker.Name = "proxyTester";

proxyWorker.Start();

それは機能しますが、スレッドが終了した後にデータソースに何が起こるのか理解できませんか? newList破壊されていませんか?

私が考えていたのは、最後にnewListを再クローンしてproxies(元のデータソース)に戻すことです

4

2 に答える 2

3

あなたの混乱は、.NET オブジェクトがそれを作成したスレッドに関連付けられていると考えているという事実から生じていると思います。そうではなく、プロセス内のすべてのスレッドが同じ GC ヒープを共有します。あるスレッドで作成された List<> オブジェクトは、別のスレッドの List<> と変わらず、それを作成したスレッドを存続させることは決してありません。

スレッド化の問題は、スレッドセーフではないクラスがたくさんあることです。これは、どの UI コンポーネントにも当てはまります。できないことは、別のスレッドからそのようなクラス オブジェクトのプロパティを割り当てることですが、そのプロパティ値は UI スレッドでも使用される可能性があります。UI コンポーネントのほとんどすべてのプロパティには、その制限があります。プロパティの割り当てが直接表示されないため、データ バインディングは特に厄介です。バインディングが設定する他のすべてのプロパティではなく、DataSource のみを設定します。Control.BeginInvoke または Dispatcher.BeginInvoke を使用すると、コントロールを作成したのと同じスレッドでプロパティ値が設定されるため、スレッド セーフの問題が解決されます。

于 2012-04-14T17:21:02.937 に答える
2

それは「1 対 1」の C# ガベージ コレクションです

new listを通じて参照されますgcProxies.DataSource

そのリストへの参照がなくなるまでは問題ありません。

「リスト」に関して特定の「クロススレッド」の問題がない限り、クロススレッドにアクセスするか、あるスレッドで作成して別のスレッドで使用している場合は、すべて問題なく動作します。
ここでは、初期化するだけで、DataSource を介する以外は二度と使用しないので、すべて問題ありません。

お役に立てれば

編集:コメントに答えるために、少し単純化しています

偶然オブジェクトを作成したスレッドは、オブジェクトの「ライフサイクル」とは何の関係もありません。つまり、スレッドはオブジェクトを所有していません。アプリケーションドメインはそうします(これは範囲外です)が、スレッドの境界を「越える」か、好きなことをすることができますが、コード/オブジェクトを同期する必要があるだけです。

于 2012-04-14T13:38:41.693 に答える