ここから本文です

VB.Net DataGridViewのマルチスレッドについて 環境 windows xp 言語 vb.net ...

nic********さん

2012/6/412:54:15

VB.Net DataGridViewのマルチスレッドについて

環境 windows xp
言語 vb.net

dv = new DataView(DataTable)
DataGridView.DataSource = dv
のようにバインドしています。

DataTableを別スレッドからデータの変更または追加をしてDataGridViewに反映したいと思っています。
(非同期的に通信を行うので別スレッドからデータ変更追加になります。)

その際にInvokeは必要なのでしょうか?

一度テストでやってみたときにはInvokeのエラーが出たような(?)気がしていたんですが、
クラスで抽象化した際にもう一度テストをやってみてみたらエラーがでないんで
あれ? っておもっています。

DataGridView自体はフォームのデザイン画面で貼り付けています。(動的生成ではないです)

分かる人いましたら、どうかよろしくおねがいします。

補足簡易テストをしてみたんですが、
DataTableにデータを追加してもエラーがでません。
(エラー内容は「有効ではないスレッド間の操作」)
ですが、DataGridView.Refreshなどをすると上記のエラーがでます。
なぜエラーが出たり出なかったりするのですか?

閲覧数:
2,541
回答数:
1
お礼:
250枚

違反報告

ベストアンサーに選ばれた回答

[Invoke の要/不要の件]

どのような条件の場合でも、別のスレッドとデーターをやり取りする場合は、Invoke が必要です。
メインのルーチン(Formクラスのある処理部)もスレッドだからです。
よって、そのスレッドであるメインルーチンが、別のスレッド(通信処理部)とデーターをやり取りするのですから、Invoke は必要です。
もしも Invoke を使わない場合は、スレッドへのアクセス用の他の機能を使う必要があります。
すなわち、正確に言い直せば、
「どのような条件の場合でも、メインルーチン(メインスレッド)と別スレッドとデーターをやり取りする場合は、Invoke 等の何らかのスレッド用機能でやり取りする必要があります」
と言う回答になります。

よって、もしも質問内容が、
「Invoke以外のスレッド用機能でアクセスしても良いのか」
と言う意味で質問されたのでしたら、
「Invoke でなくても、他のスレッド用機能を使っても構いません」
と言う回答になります。

なお、エラーの状況によっては、Invoke 以外のスレッド用機能を使ったほうが良い場合もあります。





[スレッドの同期/非同期の特質]

スレッドへのアクセスでは、同期のものと非同期のものがあります。

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1388083833

上記は、概念の説明でしたので、実際の機能名までは書きませんでした。
スレッドの同期呼び出しでは、Invoke()メソッドを使います。
スレッドの非同期呼び出しでは、BeginInvoke()メソッドを使います(BeginInvoke()メソッド と EndInvoke()メソッドを組み合わせて使用)。
すなわち、上記参照先での

おはよう
おはよう
こんにちは
おはよう
おはよう

となるほうがBeginInvoke()メソッドを使った場合です。
これに対して、

おはよう
おはよう
おはよう
おはよう
おはよう
こんにちは

となるほうがInvoke()メソッドを使った場合です。
よって、質問の件では、Invokeを使っていると言うことなので、後者のほうです。
すなわち、「おはよう」の連続表示が終わるまでは、「こんにちは」は表示されません。
これを質問内容の場合に置き換えて、下記に説明します。

例えば、通信処理用スレッドからDataGridViewへのデーター書き込みを行なう前に、ユーザーがDataGridViewに直接書き込みを行なっているとします。
この場合、メインスレッドでの処理(ユーザーの直接操作)が終わるまでは、通信処理用スレッドからのデーター書き込みを行なえません。
なお、上記の「メインスレッドでの処理」は、ユーザーの直接操作だけではなく、例えばシステムが影で行なっている処理なども含まれます。

おそらく、上記の類のことで、エラーが出たのだと思います。




[DataGridView.Invoke について]

上記説明で、心当たりがある場合は、「非同期呼び出しのBeginInvoke()メソッドを使ったほうが良いのではないか」と思うでしょう。
しかし、DataGridView コントロールに備え付いているスレッド機能は、Invoke()メソッドのほうで、BeginInvoke()メソッドはありません。





[スレッドの非同期呼び出しを行なう場合]

以上より、もしも「非同期呼び出しにしたほうが良い」と判断した場合は、コントロールに備え付いている機能は、あてになりません。
よって、一般のスレッドの作る方法で、スレッドを作成をする必要があります。
そして、その作成したスレッドは、DataGridView を操作(アクセス)する処理を記述します。
なお、そのスレッド作成方法は、BeginInvoke()メソッドを使う方法になります。
よって、未経験でしたらBeginInvoke のキーワードで検索して、サンプルを探して下さい。
なお、BeginInvoke()メソッドは、難しいと思うかも知れません。
その場合は、BeginInvoke() でなくても構いません。
よく、単純な(基礎的な)スレッド作成方法で、無限ループの処理をスレッドにするサンプルは、見つかると思います(無限ループのプログラムは、処理を占有してしまうので、スレッドでの処理にします)。
その方法を使えば良いです。
すなわち、DataGridView へのアクセスを無限ループ内に置き、常時、アクセスの受け付けを待機している状態にします。
なお、DataGridView 用スレッドと、通信処理用スレッドとの間でのデーターのやり取りは、スレッド用の通信機能を使います。
この場合は、System.Threading.Monitor クラスを使って、スレッド間通信を行なうと良いです(Monitor クラスは、スレッド間の共有変数をアクセスする際に、その変数をロックして、アクセスが終わったらロック解除をするだけです。よって、比較的簡単です)。





なお、時々のエラーならば、再通信をすると言った運用上の対応で構わないと思います。





[補足の件]

もう余白がないので書き切れないです。
上記の続きとして書くので、もうひとつ質問を用意して下さい。

質問した人からのコメント

2012/6/4 18:00:13

降参 abiko_tetuさん ありがとうございます^^
もうひとつ質問をさせていただきました。

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる