0

Control.Invoke を使用してワーカー スレッドから GUI コントロールを更新することに関して、SO には多くの質問/回答がありますが、更新せずにコントロールからデータを読み取るというトピックを明確にすることができませんでした。

例: Windows フォームに DataGridView があります。ワーカー スレッドから、DGV 上の特定のセルの値を確認したいのですが、値を更新する必要はありません。ワーカー スレッドから、唯一のパラメーターとして DataGridView オブジェクトを受け取るメソッドを呼び出し、メソッドは DataGridView 内の特定のセルを調べますが、変更はしません。この場合、.Invoke を使用する必要がありますか?

現在、コードは .Invoke を使用せずに明らかな警告なしで正常に実行されているように見えます。ただし、DGV を更新するのではなく、DGV のセルを変更せずに見るだけなので、これが安全かどうかはわかりません。

誰かがこれに光を当てることができますか?これが重複した質問である場合は申し訳ありませんが、マルチスレッドの状況で更新/変更せずにコントロールを読み取るだけに焦点を当てた他の質問は見つかりませんでした。

ありがとう。

ワーカー スレッドから呼び出されるメソッドの例:

    private DataGridViewRow getRowObject(DataGridView dgv)
    {
        foreach (DataGridViewRow row in dgv.Rows)
        {
                if ((int)dgv[specialColumn, row.Index].Value == 100)                    
                return row;
        }
    }
4

2 に答える 2

6

InvalidOperationException が存在しないことは、スレッド セーフを証明するものではありません。Winforms は、非常に特定のメンバー アクセスのチェックのみを実行します。基になるオペレーティング システム コールで使用される Handle プロパティを使用する必要があります。これはあなたのコードでは決して起こりません.DataGridViewはWindows呼び出しからデータを取得しません.

スレッドセーフではない明らかなケースは、ユーザーがグリッド値を編集し続けることを許可する場合です。もちろん、スレッドの実行と完全に同期されていない予測不可能な値が得られます。これを防ぐには、DataGridView.ReadOnly プロパティをtrueに設定する必要があります。

次に、DataGridViewCell がその値を取得する方法が非常に重要になります。自明ではないケースは、CellValueNeeded イベントが発生する場合、またはグリッドがデータバインドされている場合です。現在、そのコードがスレッドセーフかどうかに完全に依存しています。

于 2014-06-09T19:06:01.567 に答える
2

安全ではありません。

コントロール、特に dataGrid は内部で Collection クラスを使用します。他のスレッドが編集する可能性があるときに読み取るのは安全ではありません。

一部のプロパティ (SelecteItem など) を読み取るには、Handle が必要であり、クロススレッド警告例外をトリガーします。

于 2014-06-09T18:54:05.167 に答える