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

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

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

Re[4]: 並列処理の方法について


(過去ログ 103 を表示中)

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

■61480 / inTopicNo.1)  並列処理の方法について
  
□投稿者/ tomo (8回)-(2011/08/16(Tue) 11:40:19)

分類:[.NET 全般] 

[ソフト]VB2010Express
[環境]Windows XP Professional(32bitOS)


お世話になります。
並列処理の方法について質問です。
「BackgroundWorker」と「System.Threading.Thread」の差についてご教示頂きたいと
思っております。


【背景】

現在、3台のネットワークカメラで画像を同時取込させようとしています。

トリガをタイマで1ms間隔で監視し、トリガ(撮影開始の信号)が入力されると
BackgroundWorkerを3つ利用して、各カメラごとに「画像撮影→外付けHDDに保存」
という作業を並列処理で行なっています。

例.
Call Backgroundworker1():camera1の取込プログラム呼び出し
Call Backgroundworker2():camera2の取込プログラム呼び出し
Call Backgroundworker3():camera3の取込プログラム呼び出し

しかし、かなりの頻度でcamera3の取込が遅れてしまいます。
そこで、試しにBackgroundWorkerの使用を止めて、System.Threading.Threadを利用すると
大幅な遅延が解消されました。

使い勝手はBackgroundWorkerの方が良いので、そちらを使いたいと思っているのですが
改善策などはあるのでしょうか??

宜しくお願い致します。



引用返信 編集キー/
■61482 / inTopicNo.2)  Re[1]: 並列処理の方法について
□投稿者/ Hongliang (799回)-(2011/08/16(Tue) 12:21:39)
BackgroundWorker はスレッドプールを使ってスレッド処理を実現していますが、
スレッドプールは、既定では CPU の個数分の起動済みスレッドが待機しており、処理が渡された場合まずその数だけの処理を開始します。
その後、スレッドプールの管理するスレッドが一定時間(.NET 4 では 1 秒になっているみたい)占有されている場合、新たに一つスレッドを起動し次の処理を待機します(もちろん、すでに起動待ちキューに処理が待機しているなら直ちにその処理に割り当てられます)。
スレッドプールの起動待ちスレッド数は ThreadPool.SetMinThreads で設定できますが、スレッドプールは BackgroundWorker 以外にも利用される共有資源なので、これに頼るのは安定しないかもしれません。

起動時にあらかじめ BackgroundWorker を RunWorkerAsync した上で DoWork 開始直後に ManualResetEvent を WaitOne しておき、処理開始したいときに ManualResetEvent を(UI スレッドで)Set する、という方法はいかがでしょうか?

// 1ms は努力目標ってことでいいんですよね?
引用返信 編集キー/
■61486 / inTopicNo.3)  Re[2]: 並列処理の方法について
□投稿者/ tomo (9回)-(2011/08/16(Tue) 15:14:50)
> Hongliangさん

ご返信ありがとうございます。勉強になります。
1msは努力目標です。「できるだけ早く実行する!」という気持ちの表れです。



本題ですが、VBを始めてから日が浅いので解釈が間違っていたらご指摘ください。


書き忘れてましたが、現状はCore2Duoのパソコンを使ってます。

■待機中のスレッドプール×2つ(既定)
  ↓
■3つのBackgroundWorkerを実行すると、3つめの処理が遅れる場合がある
(ThreadPool.SetMinThreadsで待機中の起動済みスレッドを増やすことで改善. ※動作は不安定となる可能性もあり)

ということであってますでしょうか?



> 起動時にあらかじめ BackgroundWorker を RunWorkerAsync した上で DoWork 開始直後に ManualResetEvent を WaitOne しておき、処理開始したいときに
> ManualResetEvent を(UI スレッドで)Set する、という方法はいかがでしょうか?


教えて頂いた方法ですが、

■BackgroundWorkerを「実行→待機状態」にしておくことで、新たに1つスレッドを起動させて3つの処理を待機状態にする.
  ↓
■トリガ(撮影開始の信号)が入力されると、待機中のBackgroundWorkerを一気に実行する.(処理待ちは発生しない?)

となるんでしょうか?
質問ばかりで申し分けありませんが、何卒宜しくお願い致します。






引用返信 編集キー/
■61489 / inTopicNo.4)  Re[3]: 並列処理の方法について
□投稿者/ Hongliang (800回)-(2011/08/16(Tue) 15:39:06)
> ■待機中のスレッドプール×2つ(既定)
>   ↓
> ■3つのBackgroundWorkerを実行すると、3つめの処理が遅れる場合がある
> (ThreadPool.SetMinThreadsで待機中の起動済みスレッドを増やすことで改善. ※動作は不安定となる可能性もあり)
>
> ということであってますでしょうか?
動作が不安定になるというと何か違和感ありますが。
たとえば SetMinThreads で最小スレッド数を 3 にした場合、他にスレッドプールのスレッドを占有している処理がすでに存在していたら結局 3 つのうちの最後の 1 スレッドはスレッドの割り当てが遅れることになるってことですね。
いつ誰がスレッドプールを使うのかは完全に把握するのはなかなか困難であるため(後からコード修正した結果増えるかもしれませんし)、最小スレッド数をこの値にすれば確実に遅延なしでいける、という保証が出来ないと言うことです。>安定しない

> ■BackgroundWorkerを「実行→待機状態」にしておくことで、新たに1つスレッドを起動させて3つの処理を待機状態にする.
>   ↓
> ■トリガ(撮影開始の信号)が入力されると、待機中のBackgroundWorkerを一気に実行する.(処理待ちは発生しない?)
何を質問されたいのかちょっと分かりかねます。
引用返信 編集キー/
■61498 / inTopicNo.5)  Re[4]: 並列処理の方法について
□投稿者/ なちゃ (499回)-(2011/08/16(Tue) 21:41:33)
根本的に、スレッドプールは即座に処理を開始したいといった明示的な制御を要する場合には向きません。
色々工夫することはできても、元々向いている仕組みではありませんので、明示的にThreadを使う方がよいです。
もちろん、BackgroundWorkerと同じような仕組みを、スレッドプールではなくThreadで明示的に制御する形で作ってもいいですが。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -