DOBON.NET DOBON.NETプログラミング掲示板過去ログ

【VB .Net】データグリッドビューでスクロールバーがフリーズする

環境/言語:[Windows Vista VB2008 .NET Framework 3.5]
分類:[.NET]

お世話になります。
VB2008の開発において問題が発生しているので、どなたか解決方法をご存知でしたら教えてください。

データグリッドビューを使用して、処理結果を明細行に表示させる画面があります。
この画面は、納品書のバーコードを読み込み、読み込み結果をデータグリッドに表示させるというものです。
納品書は複数枚連続読み込み可能で、1枚ずつ読み込んではその結果を明細行追加して表示するという処理を行っています。

その明細行追加は、
 Me.データグリッドビューコントロール名.Rows.Add()
で行っています。

で、読み込み件数が多く、画面の明細部に表示しきれない場合は、スクロールバーが自動表示され、行追加されていきます。
ここで問題なのですが、全納品書の読み込み終了後に画面を触ると、そのスクロールバーがフリーズする、
厳密には色が真っ黒になり固まってしまいます。
画面自体もフリーズしてしまい、どうにもならなくなってしまいます。
読み込み件数が少ないスクロールが発生しないケースではこのような画面フリーズは発生しないです。

コーディングに問題があるのか、データグリッドの設定に問題があるのか、何が原因か解らず困っています。
どなたか、同様の事象を経験され、解決方法をご存知の方いらっしゃらないでしょうか?

どうぞ、お力添え宜しくお願いします。
> Me.データグリッドビューコントロール名.Rows.Add()

なんて使い方したことがないため判りませんが、↓と同じ現象かも知れません。

http://dobon.net/vb/bbs/log3-26/15520.html
ひらぽんさん、ご回答ありがとうございます。

教えて頂いたURLの内容を確認したのですが、ソースの内容からして
どうもVB.NETではなさそうな感じです。

可能でしたら、VB.NETでの解決方法をご教授頂けないでしょうか?
宜しくお願いします。
■No26222に返信(Purple Hazeさんの記事)
> ひらぽんさん、ご回答ありがとうございます。
>
> 教えて頂いたURLの内容を確認したのですが、ソースの内容からして
> どうもVB.NETではなさそうな感じです。
>
> 可能でしたら、VB.NETでの解決方法をご教授頂けないでしょうか?
> 宜しくお願いします。

> http://dobon.net/vb/bbs/log3-26/15520.html

のソースは C# ですが、VB.NET でも使っているクラスは全く同じです。
VB.NET に置き換えて考えてみてはいかがでしょうか。
■No26222に返信(Purple Hazeさんの記事)
> ひらぽんさん、ご回答ありがとうございます。
>
> 教えて頂いたURLの内容を確認したのですが、ソースの内容からして
> どうもVB.NETではなさそうな感じです。
>
> 可能でしたら、VB.NETでの解決方法をご教授頂けないでしょうか?
> 宜しくお願いします。
>
.NET TIPS : Windowsフォームで別スレッドからコントロールを操作するには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/312ctrlinvoke/ctrlinvoke.html

でもその前に、提示されたスレッドで言及されている状況(バックグラウンドのスレッドからコントロールを操作しようとしている)に心当たりがあるかどうかをはっきりさせたほうがいいと思うけど。
ひらぽんさん、みきぬさん、ご回答ありがとうございます。

> でもその前に、提示されたスレッドで言及されている状況(バックグラウンドのスレッドからコントロールを操作しようとしている)に心当たりがあるかどうかをはっきりさせたほうがいいと思うけど。

別スレッド(バックグラウンドのスレッドからコントロールを操作しようとしている)ということは行っておりません。
単純にDataGridViewに、
Me.データグリッドビューコントロール名.Rows.Add()
で、行追加しているのみです。

う〜ん、何を行えば問題解決するのか分かりません。。。
行追加の度に、画面のリフレッシュでも行えば解決するのでしょうか?
もし何か他の解決策があれば、ご教授お願いします。
一応確認ですが、DataGridView には DataSource を設定してないのですよね?

#最初の文面からはそう受け取れますが・・・
ひらぽんさん、ご回答ありがとうございます。

> 一応確認ですが、DataGridView には DataSource を設定してないのですよね?
> #最初の文面からはそう受け取れますが・・・

はい、DataSourceは何も設定していません。
設定の有無によって、何か変わってきますでしょうか?
正直ちょっとここまでの情報だけでは判らないです。
また最初の方で

>> Me.データグリッドビューコントロール名.Rows.Add()
> なんて使い方したことがないため判りませんが・・・

と回答したとおり、普通は DataSource に DataTable を設定して使うものなので、
(そのための 『Data』GridView です)
DataGridView をリストビューの様に扱ったことがないため、何とも判りません。

試しに1万行 Rows.Add() を実行してみましたが、
1万行の DataTable 設定するよりも遥かにパフォーマンスが悪いですね。
この辺りに鍵がありそうですが・・・

もうちょっと前後のコードや、何行データを設定しているか等
可能な限り情報開示して頂けませんか?でないと正直推測すらできません。
■No26209に返信(Purple Hazeさんの記事)
> で、読み込み件数が多く、画面の明細部に表示しきれない場合は、スクロールバーが自動表示され、行追加されていきます。
> ここで問題なのですが、全納品書の読み込み終了後に画面を触ると、そのスクロールバーがフリーズする、
> 厳密には色が真っ黒になり固まってしまいます。

件数の問題なのか、表示させようとしているデータの問題なのか、
プログラムの問題なのか、環境の問題なのか、.NET/OS 側の不具合なのか、
調べていく必要がありそうですね。

・フリーズ後、数時間放置してみても、表示されませんか?
 (処理に時間がかかっているだけという可能性を考慮)
・スクロールバーが発生するのは、データ数が何件以上の時ですか?
・何件までであればフリーズせず、何件以上であればフリーズしますか?
 あるいは件数ではなく、特定の行を表示させる際にフリーズしていませんか?
・フリーズ時、表示すべき総データ量は、およそ何バイトぐらいになるのでしょうか?
 (データ量が多すぎて、メモリ確保に時間がかかっている可能性を考慮)
・他の PC で実行した場合にもフリーズしますか?
 (Service Pack の違いやディスプレイドライバなど、環境依存の問題の可能性)
・DataGridView のイベントを、何か利用されていますか?
 (イベント内で時間のかかる処理を行っていませんか? たとえば、0.15 秒で
 終わる処理でも、それが1000回呼び出されれば 2分半という時間を要します)
・DataGridView に、何か追加の設定をしていますか?
 (何も設定していない初期設定のDataGridViewでも結果は一緒ですか?)

> コーディングに問題があるのか、データグリッドの設定に問題があるのか、何が原因か解らず困っています。
既に指摘されていますように、Rows.Add はパフォーマンス上の問題があるので、
DataSource に DataSet/DataTable をバインドされる事をお奨めします。

なお、バインドしてもパフォーマンス上の問題が改善されない場合、
DataGridView の“仮想モード”を使うという選択肢もあるのですが、
記述すべきコードが圧倒的に増えてしまうので、あまりお奨めしません。
ひらぽんさん、魔界の仮面弁士さん、どうもありがとうございます。

すいません、実業務がかなり多忙で、こちらに回答できませんでした。
現在も同じ状況ですので、もうしばらくしましてから、出来る限りの情報を
提示させて頂きます。

その際は、すいませんがお手隙の時にでもご覧頂けるとありがたいです。
では宜しくお願いします。
ひらぽんさん、魔界の仮面弁士さん。
お世話になります。
随分間が空いてしまいましたが、ご覧になられたらご回答お願いします。

以前までのやりとりで、一つ訂正があります。
私は別スレッドで処理を行っていないと申しましたが、誤りでした。
データグリッドの行追加は、画面とは別スレッドで行っています。

具体的には、まず画面のSTARTボタンをクリックすることで、バーコードリーダ(以下、実機)の
ドライバの読込み処理をキックします。
この命令によって実機が納品書のバーコードを読込み、結果をドライバに返して画面のデータグリッドに描画します。
ドライバは、実機のトレイにセットされた納品書が無くなるまでこれらの処理(1枚納品書を読込んでは、画面への描画)
を繰り返します。
よって、データグリッドの描画は画面とは別スレッドで行っています。
この肝心なところを誤ってお伝えしてしまいました。
大変申し訳ありません。

あと、実装でより詳しくお伝えすることとして、
画面の明細行は約25行くらいです。
これ以上読込み処理が行われるとスクロールバーが表示され、不具合が発生します。(約30件ほどで発生)
明細の1レコードのデータサイズは、せいぜい300〜400バイトくらいです。
他の端末でも同じ事象が再現します。

最後に、行追加のコードですが、
Me.Dgv_Detail.Rows(件数).Cells(列名).Value = detaildata(列名).ToString();
というように行っています。これを明細の列数分、行っています。(列数:22)
データを格納するdetaildataは、ハッシュテーブルを使っています。
描画処理自体は、さほど複雑ではないので、付け加える情報としましては、これくらいになります。

以上です。
また何かお分かりでしたら、アドバイスお願いします。
■No26332に返信(Purple Hazeさんの記事)
> 私は別スレッドで処理を行っていないと申しましたが、誤りでした。
> データグリッドの行追加は、画面とは別スレッドで行っています。

ワーカースレッドが、DataGridView あるいはバインドされた DataTable 等を
操作していないかどうかを確認してみてください。

データの提供は、ワーカースレッドに担当させても良いですが、
コントロールの操作は、メインスレッドのみが担当するようにしてください。

DOBON.NET | プログラミング道 | プログラミング掲示板