C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: DBデータ読み込み時のマルチスレッド処理について


(過去ログ 56 を表示中)

[トピック内 21 記事 (1 - 20 表示)]  << 0 | 1 >>

■31744 / inTopicNo.1)  DBデータ読み込み時のマルチスレッド処理について
  
□投稿者/ pgm300 (3回)-(2009/01/28(Wed) 13:18:49)

分類:[C#] 

2009/01/28(Wed) 13:20:06 編集(投稿者)

OS: Vista Business
IDE:VS2008
言語:C#
形態:Windows Form

こんにちは。

マルチスレッドプログラミングについて質問させてください。

良くサンプルにあるSystem.ThreadingのThreadクラスを用いて、
DBからデータ読み込み中に、フォームのプログレスバーをインクリメント
させて、処理しています(フリーズしていません)という感じにしたいのです。

コードとしては、Thread.Startを用いており、確かにスレッドは
出来ているが、当方の希望する動きになっていないのです。

具体的に言いますと、
処理として
1. ループとThread.Sleepを用いて、1秒おきにProgressバーの
  値をインクリメントする処理。
2. DBからデータを読み込む処理

1と2は別スレッドになります。

2の処理は、DBからデータを読み込むのに、約30秒かかります。

処理の流れとしては、

@スレッド作成・開始
ADB読み込み ← System.Data.OracleClientを使用しています。
Bスレッド処理停止

となっていますが、各処理にConsole.WriteLineで処理開始・終了時刻を
出力するようにして、実際にデバッグすると、
希望としては

@00:00:00
A00:00:01
@00:00:01
@00:00:02
@00:00:03
@00:00:04
(省略)
A00:00:30

というようにDB読み込み中にもスレッドが規則正しく動き、
プログレスバーのインクリメントを期待していたのですが、
実際には、

@00:00:00
A00:00:01
A00:00:30
@00:00:01
@00:00:02
@00:00:03
@00:00:04

というように、DB読み込みの処理に移ると、メッセージキューには
確かに書き込まれているようですが、DB読み込みが完了と同時に
(上記の図でいくと、@の後ろ4つが)
一気にメッセージが処理されてしまうような動きになっています。

ですので、はじめの1回目のインクリメントはされて、プログレスバーに
表示されますが、その後はDB読み込み完了後に、一気にインクリメント
され、全然意味のないプログレスバーになってしまっています。

この状態を回避したいと考えておりますが、ご存じの方がおられましたら、
相談に乗って頂けないでしょうか?

宜しくお願い致します。
引用返信 編集キー/
■31747 / inTopicNo.2)  Re[1]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ 倉田 有大 (429回)-(2009/01/28(Wed) 13:29:32)
2009/01/28(Wed) 13:37:33 編集(投稿者)

スレッドでプログレスバーの操作時、Invokeはされてます?

http://www.atmarkit.co.jp/fdotnet/dotnettips/312ctrlinvoke/ctrlinvoke.html

いや、DBの処理がおもかったら、GUIを作成したスレッドにもどらないから無理か失礼。
DBの処理でDoEventsをかましてやればいいと思ったけど、一個のメソッドの処理が重かったらそれもむりだし、どうすればいいんだろ?
引用返信 編集キー/
■31750 / inTopicNo.3)  Re[2]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ pgm300 (5回)-(2009/01/28(Wed) 13:33:13)
早速ありがとうございます。

> スレッドでプログレスバーの操作時、Invokeはされてます?
>
> http://www.atmarkit.co.jp/fdotnet/dotnettips/312ctrlinvoke/ctrlinvoke.html

はい、Invokeしております。
描画ができていないというわけではなく、処理が規則正しく
行われていないという感じです。
引用返信 編集キー/
■31757 / inTopicNo.4)  Re[3]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ .SHO (587回)-(2009/01/28(Wed) 13:58:51)
No31750 (pgm300 さん) に返信

スレッド化しないで、素直にConsole.WriteLineしているところで
Progressバーを進めちゃダメなんですか?
引用返信 編集キー/
■31759 / inTopicNo.5)  Re[4]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ pgm300 (7回)-(2009/01/28(Wed) 14:02:10)
No31757 (.SHO さん) に返信
> ■No31750 (pgm300 さん) に返信
>
> スレッド化しないで、素直にConsole.WriteLineしているところで
> Progressバーを進めちゃダメなんですか?

すいません。DBからデータをSELECTしている時間が約30秒あり、
その時間中にフリーズしていない感じを出したいので、
Console.WriteLineしているところでは、あまり意味がないのです。
返信ありがとうございます。



引用返信 編集キー/
■31765 / inTopicNo.6)  Re[5]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ .SHO (592回)-(2009/01/28(Wed) 14:37:08)
No31759 (pgm300 さん) に返信

> すいません。DBからデータをSELECTしている時間が約30秒あり、
> その時間中にフリーズしていない感じを出したいので、
> Console.WriteLineしているところでは、あまり意味がないのです。
> 返信ありがとうございます。

DB読み込みをしていない方のスレッドだけのConsole.Writeline出力が

> @00:00:00
> A00:00:01
> A00:00:30
> @00:00:01
> @00:00:02
> @00:00:03
> @00:00:04

となるのですか?

引用返信 編集キー/
■31766 / inTopicNo.7)  Re[6]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ pgm300 (8回)-(2009/01/28(Wed) 14:50:35)
> DB読み込みをしていない方のスレッドだけのConsole.Writeline出力が
>
>>@00:00:00
>>A00:00:01
>>A00:00:30
>>@00:00:01
>>@00:00:02
>>@00:00:03
>>@00:00:04
>
> となるのですか?

ん?複数の処理を(出来るだけ)平行に走らせるために、
マルチスレッドプログラミングしているので、片方だけの
スレッド出力をサンプリングはしていないのですが、
仮に、DB読み込みをしていない方のスレッドだけのConsole.Writeline出力が
規則正しく

@00:00:00
@00:00:01
@00:00:02
@00:00:03
@00:00:04

であった場合、どういう考察が可能なのでしょうか?
勉強不足で申し訳ないです。。。
引用返信 編集キー/
■31767 / inTopicNo.8)  Re[6]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ みきぬ (351回)-(2009/01/28(Wed) 15:01:42)
No31765 (.SHO さん) に返信

↓のように、処理(スレッド)が2つあって、

>> 1. ループとThread.Sleepを用いて、1秒おきにProgressバーの
>>   値をインクリメントする処理。
>> 2. DBからデータを読み込む処理

1 の処理は@のメッセージを、2 の処理はAのメッセージを出力しているのだと思います。

>>@00:00:00
>>A00:00:01
>>A00:00:30
>>@00:00:01
>>@00:00:02
>>@00:00:03
>>@00:00:04

引用返信 編集キー/
■31771 / inTopicNo.9)  Re[7]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ pgm300 (9回)-(2009/01/28(Wed) 15:26:04)
> ↓のように、処理(スレッド)が2つあって、
>
> >> 1. ループとThread.Sleepを用いて、1秒おきにProgressバーの
> >>   値をインクリメントする処理。
> >> 2. DBからデータを読み込む処理
>
> 1 の処理は@のメッセージを、2 の処理はAのメッセージを出力しているのだと思います。
>
> >>@00:00:00
> >>A00:00:01
> >>A00:00:30
> >>@00:00:01
> >>@00:00:02
> >>@00:00:03
> >>@00:00:04

そうなのでしょうか?
とすると、
http://www.atmarkit.co.jp/fdotnet/mthread/mthread02/mthread02_02.html
のような説明はおかしいという風になるのでしょうか?

Aの処理が一回処理されるうちに、
@の処理は約30回処理されるのがスレッドですよね?
であることを前提とすれば、引用して頂いた

> >>@00:00:00
> >>A00:00:01
> >>A00:00:30
> >>@00:00:01
> >>@00:00:02
> >>@00:00:03
> >>@00:00:04

はおかしいと思う次第です。

はっ!もしかしてIDEでのデバッグ時にDBにデータを読み込む処理を
した時に、IDEそのもののスレッド(正確にはメッセージか?)も一時停止
するのですかね?

引用返信 編集キー/
■31785 / inTopicNo.10)  Re[8]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ みきぬ (352回)-(2009/01/28(Wed) 16:49:14)
No31771 (pgm300 さん) に返信
> そうなのでしょうか?
> とすると、
> http://www.atmarkit.co.jp/fdotnet/mthread/mthread02/mthread02_02.html
> のような説明はおかしいという風になるのでしょうか?
>
えっと、私としては、表示結果があってるか間違っているかは関係なく、
単に質問を補足したつもりなのですが、間違って説明しちゃいましたか?

# ふと思ったけど、BackGroundWorker は使ってないのかしら?
引用返信 編集キー/
■31801 / inTopicNo.11)  Re[1]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ 小心者 (7回)-(2009/01/29(Thu) 00:34:04)
2009/01/29(Thu) 01:23:27 編集(投稿者)

No31744 (pgm300 さん) に返信
> DBからデータ読み込み中に、フォームのプログレスバーをインクリメント
> させて、処理しています(フリーズしていません)という感じにしたいのです。
<途中省略>
> 2の処理は、DBからデータを読み込むのに、約30秒かかります。

DBからのデータを読み込み中の時の挙動についての質問です。
1)フリーズしているのかしていないのか判断基準は何ですか?判断基準に客観的な根拠がありますか?
2)プログレスバーはインクリメントするのですか?
3)プログレスバーをインクリメントするなら増分はどのタイミングでどう与えるのですか?
4)読み込みがいつまで経っても終わらない場合どうするのですか?

プログラムを書く前に最低限の仕様を決めておくべきかと思います。
プログラム書きながら考えるのでは順番が逆です。

ところで30秒は時間かかり過ぎの気がします。
データ量はどのくらいですか?
引用返信 編集キー/
■31804 / inTopicNo.12)  Re[5]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ 倉田 有大 (430回)-(2009/01/29(Thu) 01:25:59)
>>スレッド化しないで、素直にConsole.WriteLineしているところで
>>Progressバーを進めちゃダメなんですか?
>
> すいません。DBからデータをSELECTしている時間が約30秒あり、
> その時間中にフリーズしていない感じを出したいので、
> Console.WriteLineしているところでは、あまり意味がないのです。
> 返信ありがとうございます。

ひとつの命令文で30秒かかるのですね。
ああ、ようやく解決策思いついたかも。
DBからSELECTしているところをthreadでうごかして、
プログレスバーをSystem.Windows.Forms.Timerで動かしてはいかがですか。

引用返信 編集キー/
■31805 / inTopicNo.13)  Re[2]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ pgm300 (10回)-(2009/01/29(Thu) 01:27:31)
2009/01/29(Thu) 01:29:53 編集(投稿者)

> DBからのデータを読み込み中の時の挙動についての質問です。
> 1)フリーズしているのかしていないのか判断基準は何ですか?判断基準に客観的な根拠がありますか?

いえ、フリーズしているかどうかを判断したいのではないので、根拠等は特に考慮しないですし、
考える必要もないと考えております。

> 2)プログレスバーはインクリメントするのですか?

はい、インクリメントします。
プログレスバーは、物事の進捗をUIとして示すと同時に、プログラムが処理中であることを
最もアクティブに示すのに最適と考えております。

> 3)プログレスバーをインクリメントするなら増分はどのタイミングでどう与えるのですか?

前のスレッドにも記載しましたが、マルチスレッドプログラミングをしておりますので、
別スレッドを作成し、Thread.Sleepを用いて1秒おきにインクリメントします。

> 4)読み込みがいつまで経っても終わらない場合どうするのですか?

予期せぬエラーについてポリシーを語る必要があるのでしょうか?
DBからレコードをSELECTしてくるという処理で、読み込みがいつまでたっても
終わらないというのは明らかに予期せぬエラーが発生しているとしか考えられませんし、
もしそれを聞いてくださっているのなら、「集約エラーハンドリングしている」という
答えになりますし、大量のデータをSELECTし、結果が返ってくるのに異常な時間が
かかることを考えて頂いているのであれば、それについては
「SQLチューニングを別途行います」という答えになります。

> プログラムを書く前に最低限の仕様を決めておくべきかと思います。
> プログラム書きながら考えるのでは順番が逆です。

いえ、プログラムを書く前に仕様を考えて、実装した結果、不都合な事象に
気づけたのであって、プログラムを書きながら聞いているわけではありません。
さらに言えば、本番のプログラムに実装する前のテストプログラムにおける
検証段階で質問をさせて頂いております。

引用返信 編集キー/
■31806 / inTopicNo.14)  Re[2]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ pgm300 (11回)-(2009/01/29(Thu) 01:34:28)
> ところで30秒は時間かかり過ぎの気がします。
> データ量はどのくらいですか?

レコード件数は、四万件くらいです。
が、検証用に作成した環境ですので、実際遭遇する場面よりは、
大きめではあります。
引用返信 編集キー/
■31807 / inTopicNo.15)  Re[6]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ pgm300 (12回)-(2009/01/29(Thu) 01:37:42)
> ひとつの命令文で30秒かかるのですね。

はい!そうです!

> ああ、ようやく解決策思いついたかも。
> DBからSELECTしているところをthreadでうごかして、
> プログレスバーをSystem.Windows.Forms.Timerで動かしてはいかがですか。

ほほぅ。そうですか。
御教示頂いた内容で修正すること自体は可能なのですが、
ひとつの命令文で30秒かかるとその30秒間は別スレッドで発生した
メッセージはデキューされないということなんでしょうか?
後学のためにも教えて頂けないでしょうか?
引用返信 編集キー/
■31811 / inTopicNo.16)  Re[7]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ 倉田 有大 (431回)-(2009/01/29(Thu) 09:11:26)
> ほほぅ。そうですか。
> 御教示頂いた内容で修正すること自体は可能なのですが、
> ひとつの命令文で30秒かかるとその30秒間は別スレッドで発生した
> メッセージはデキューされないということなんでしょうか?
> 後学のためにも教えて頂けないでしょうか?

InvokeがそもそもGUIを作成したスレッドで処理させることですから、SELECTがGUIを動かすスレッド動いていますから、
SELECT文を動かしているメソッド抜けた後に、Invokeさせたメソッドが動くんじゃないかな。
引用返信 編集キー/
■31826 / inTopicNo.17)  Re[3]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ HiJun (117回)-(2009/01/29(Thu) 11:14:53)
SELECT文は、1レコード(40000という件数値)を取り出すだけですか?
それとも、データの40000レコードを取り出しているのでしょうか?

引用返信 編集キー/
■31860 / inTopicNo.18)  Re[4]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ pgm300 (16回)-(2009/01/29(Thu) 15:24:07)
No31826 (HiJun さん) に返信
> SELECT文は、1レコード(40000という件数値)を取り出すだけですか?
> それとも、データの40000レコードを取り出しているのでしょうか?

countではなく、40000レコードを取り出しです。
引用返信 編集キー/
■31885 / inTopicNo.19)  Re[5]: DBデータ読み込み時のマルチスレッド処理について
□投稿者/ HiJun (120回)-(2009/01/29(Thu) 18:15:59)
であれば 倉田有大サンも記載していますが、
SELECT文を実行した後にInvokeが走るので間隔が
空くのだと思います。

もしやるのであれば、40000件のループ処理内で、
Invokeを呼ぶようにするとか、SELECT文が早くなるように
INDEXを張ってしまうとかでしょうか?

引用返信 編集キー/
■31903 / inTopicNo.20)  Re[3]: DBデータ読み込み時のマルチスレッド処理について
 
□投稿者/ 小心者 (8回)-(2009/01/29(Thu) 21:24:27)
質問の仕方が不味かった様で、すみませんでした。

例えばプログレスバーを0%,25%,50%,75%,100%の5段階に変化させるとします。
0%と100%は良いとしても、
25%になるのは処理がどこまで進んだときでしょうか?
50%になるのは処理がどこまで進んだときでしょうか?
75%になるのは処理がどこまで進んだときでしょうか?

言い換えれば1秒おきにプログレスバーを更新するときの、
プログレスバーの増分はどうやって求めるのですか?

今回はこの辺りの仕様を決めないことにはプログラム組めないです。

仕様決めないでプログラム作るとかなりの確率で迷走しますので、
いくらテストプログラムでもやっぱり仕様は必要ですよ。

他の方からもたくさんヒント頂けてますから、
あとは仕様をしっかり決めて作るだけですね。

ただ感覚的に4万件で30秒は遅い様な気がします。
データベースおよびプログラムを根本的に見直して高速化し、
プログレスバー自体が不要になる可能性も捨て切れないですね。
引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -