.NetのBackgroundWorkerクラスについての質問

このQ&Aのポイント
  • バックグラウンドスレッドを使用するための.NetのBackgroundWorkerクラスについての質問です。
  • .NetのBackgroundWorkerクラスについて、バックグラウンドスレッドのCPU優先度やフォアグラウンドスレッドとの関係について知りたいです。
  • バックグラウンドスレッド内でのスレッド制御やフォアグラウンドスレッドへの制御移行について、教えていただけると助かります。
回答を見る
  • ベストアンサー

.NetのBackgroundWorkerクラスについての質問です。

.NetのBackgroundWorkerクラスについての質問です。 BackgroundWorkerクラスなるものを知るまでは、Threadクラス等でマルチスレッドを実装していました。 MSDNを読みながら、実装自体は非常に簡単に出来ましたが、このバックグラウンドスレッドとは如何なるものなのでしょうか。 フォアグラウンド/バックグラウンドタスクであるならば、CPU優先度(占有度)により、その実行タイミングが左右されるのは容易に想像できるのですが、バックグラウンドスレッドは、どのようにCPU優先度が決まるのでしょうか。(デスクトップWindowsでは、あまり機会がないかとは思いますが、リアルタイムな処理,クリティカルな処理を同クラスによって実装していいのか判断できませんでした。) Formクラスから生成されるということは、Formウィンドウのメッセージスレッドをフォアグラウンドスレッドとし、そのバックグラウンドスレッドといった関係になるのでしょうか。(Formウィンドウのアイドル時間にバックグラウンドスレッドが実行されるという理解であっていますでしょうか。) また、スレッド内でのsleep()呼出しで、スレッドは別スレッドに制御が切り替わるハズだったと思いますが、バックグラウンドスレッド内でThread::Sleep()呼出しをした場合、必ず、フォアグラウンドスレッドに制御が移り、フォアグラウンドスレッドのアイドル時間が発生するまで、バックグラウンドスレッドへ制御が戻ることがないということでしょか。(各スレッドへいつ制御が移るのか分かりませんでした。) ご回答、または、参考サイト,参考文献等、教えてくださると非常に助かります。

質問者が選んだベストアンサー

  • ベストアンサー
  • reset_cat
  • ベストアンサー率68% (94/138)
回答No.2

>sleep()ではなく、スレッドが待機状態(windows apiでいう、WaitForSingleObject 等による待機状態)であった場合も、変わらず、スレッド実行されてしまうので しょうか。 >バックグラウンドスレッドを複数生成し、シグナル送信で、次々と実行スレッド を変えていければ良いかなぁと考えていますが、回答頂いた内容から想像すると、 割当てられた時間待機しているだけになってしまうような気がします。 WaitForSingleObject等の場合、指定時間ではなくオブジェクトがシグナル状態になるまで待機するものです。こちらを使った場合は、割り当てられた時間待機しているだけということはなくなります。 オブジェクトにはミューテックス、セマフォ、イベントなどの同期オブジェクトのほか、プロセスやスレッド等も対象とすることができます。 >仮に、あるプロセスにフォアグラウンドスレッドA,バックグラウンドスレッドa1,a2しか存在しないとして、 >1.A,a1,a2を待機状態へ >2.A,a1,a2のタイムスライスが、他のプロセスへ渡される >3.a1へシグナル送信 >4.a1実行 >windows系osである以上、他プロセスとのCPUの取り合いが、ある程度までしかコントロール出来ないのは、あきらめています。 次に実行するスレッドの決定は、優先度を加味したラウンドロビン方式だったかと思います。 上記のような動作をある程度実現するには、先のWaitForSingleObject系とイベントを組み合わる方法になるかと思います。 あと、プロセスにも優先度があります。この動作をできる限り優先的に行いたいのであれば、プロセス優先度を通常より高く設定しておく方法が考えられます。これを行えば他のプロセスより優先的にタイムスライスを割り当てられるようになります。ただし、この設定を行った場合、他の操作が遅くなったり、場合によっては動作停止している状態に陥る恐れもあります。 優先度の定義については参考URLが表になっていましたので、参考に挙げておきます。(英語ですが・・・)

参考URL:
http://msdn.microsoft.com/en-us/library/ms685100(VS.85).aspx
V10A4-S
質問者

お礼

お礼を申し上げるのが、遅れ申し訳ありませんでした。 今回windowsである程度のリアルタイム性を保持した機構を検討しており、勉強すべき点が多くあり、質問させて頂きました。 とりあえず、本件は、これでクローズとさせて頂きますが、また、お力を借りる時は、よろしくお願い致します。

その他の回答 (1)

  • reset_cat
  • ベストアンサー率68% (94/138)
回答No.1

>BackgroundWorkerクラスなるものを知るまでは、Threadクラス等でマルチスレッドを実装していました。 >MSDNを読みながら、実装自体は非常に簡単に出来ましたが、このバックグラウンドスレッドとは如何なるものなのでしょうか。 BackgroundWorkerクラスは一種のスレッドクラスですが、Threadクラスとは違ってフォームデザインモードで配置できます。 >フォアグラウンド/バックグラウンドタスクであるならば、CPU優先度(占有度)により、その実行タイミングが左右されるのは容易に想像できるのですが、バックグラウンドスレッドは、どのようにCPU優先度が決まるのでしょうか。(デスクトップWindowsでは、あまり機会がないかとは思いますが、リアルタイムな処理,クリティカルな処理を同クラスによって実装していいのか判断できませんでした。) CPU優先度というのはスレッド優先度のことでしょうか?ThreadクラスではPriorityプロパティで設定できますが、BackgroundWorkerクラスではそれに該当するものがありません。確かNormal優先度だったかと思います。 >Formクラスから生成されるということは、Formウィンドウのメッセージスレッドをフォアグラウンドスレッドとし、そのバックグラウンドスレッドといった関係になるのでしょうか。(Formウィンドウのアイドル時間にバックグラウンドスレッドが実行されるという理解であっていますでしょうか。) そのFormクラスがメインフォームであるのならば、Formウィンドウのメッセージスレッドがフォアグラウンドスレッドになっていますが、そのフォームがサブフォームであり、別のスレッドから生成されている場合はフォアグラウンドスレッドにはなりません。 また、BackgroundWorkerクラスは内部でスレッドを生成して実行要求があるまで待機しつづけています。実行状態になった場合、Formメッセージスレッドがいくら忙しくても、黙々とバックグラウンド処理をし続けています。そのため、オブジェクトをFormが所有しているだけで、スレッド間での関連性はありません。 >また、スレッド内でのsleep()呼出しで、スレッドは別スレッドに制御が切り替わるハズだったと思いますが、バックグラウンドスレッド内でThread::Sleep()呼出しをした場合、必ず、フォアグラウンドスレッドに制御が移り、フォアグラウンドスレッドのアイドル時間が発生するまで、バックグラウンドスレッドへ制御が戻ることがないということでしょか。(各スレッドへいつ制御が移るのか分かりませんでした。) 各スレッドにはタイムスライスが設定されており、CPUでその時間内スレッドを実行すると中断され、別のスレッドに切り替わって実行がされてゆきます。 Sleepメソッドは、そのスレッドの実行を指定時間中断するものですが、同時にそのスレッドに残っているタイムスライスを放棄する機能もあります。タイムスライスを放棄しているので、そのスレッドが即時中断され、別のスレッドが実行されることになります。ただし、スレッドが中断されたあと、次に実行されるスレッドがどれになるかはわかりません。別のプロセスが所有するスレッドかもしれないからです。 なので、「Sleepメソッドを呼び出したらフォアグラウンドスレッドに実行が移る」というのは間違いです。

V10A4-S
質問者

お礼

返信が遅れ、申し訳ありません。 回答ありがとうございます。 概ね、予想していた通りでしたが、バックグラウンドスレッドの実行時間、及び、中断タイミングについては、理解が間違っており、参考になりました。 フォアグラウンド/バックグラウンドスレッドに関わらず、各々のスレッドにおいて、必要な時には、割り当てられたCPU実行時間を有効活用したいと考えています。(RealTime unixのマルチタスクをイメージして頂けると、一番近いです。) sleep()ではなく、スレッドが待機状態(windows apiでいう、WaitForSingleObject等による待機状態)であった場合も、変わらず、スレッド実行されてしまうのでしょうか。 バックグラウンドスレッドを複数生成し、シグナル送信で、次々と実行スレッドを変えていければ良いかなぁと考えていますが、回答頂いた内容から想像すると、割当てられた時間待機しているだけになってしまうような気がします。 仮に、あるプロセスにフォアグラウンドスレッドA,バックグラウンドスレッドa1,a2しか存在しないとして、 1.A,a1,a2を待機状態へ 2.A,a1,a2のタイムスライスが、他のプロセスへ渡される 3.a1へシグナル送信 4.a1実行 windows系osである以上、他プロセスとのCPUの取り合いが、ある程度までしかコントロール出来ないのは、あきらめています。 質問に質問を重ねる形になり、申し訳ありません。 タスク,スレッドのCPU割当て方法がどうなっているのか知りたいのですが、参考になるサイト、本等、お教え願えますと、助かります。

関連するQ&A

  • BackgroundWorkerについて(C#)

    C#でBackgroundWorkerを使ったプログラムを試しています。 Windows Form上にButtonとProgressBarを設置して以下のプログラムを 動作させると、プログレスバーが終了するまえに”終了”が出てしまいますが これはどうしてでしょうか? よろしくお願いいたします。 using System; using System.ComponentModel; using System.Threading; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { button1.Enabled = false; Random rand = new Random(); BackgroundWorker bgWorker = new BackgroundWorker(); bgWorker.DoWork += ((sender2, e2) => { for (int i = 0; i < 10; i++) { Thread.Sleep((int)(rand.NextDouble() * 500)); bgWorker.ReportProgress((i + 1) * 10); } }); bgWorker.RunWorkerCompleted += ((sender2, e2) => { button1.Enabled = true; bgWorker.Dispose(); MessageBox.Show("終了"); }); bgWorker.ProgressChanged += ((sender2, e2) => { progressBar1.Value = e2.ProgressPercentage; }); bgWorker.WorkerReportsProgress = true; bgWorker.RunWorkerAsync(); } } }

  • VC++

    フォームアプリを作成しており、実装に関して不明点があるため質問させて頂きます。 やりたいこととしては、Formでないファイル(クラス)でFormのコンポーネントを 操作したいことです。 具体的に、重たい処理を別スレッドで処理させて、処理中の経過をFormの プログレスバーに表示することです。 重たい処理は別ファイル(クラス)で行います。 以下に大まかなコードを記載します。 ----------------------------------------------------- ---- Form.h ---- #include "Main.h" namespace XXX { public ref class Form1 : public System::Windows::Forms::Form {  Main^ mMain;    // ボタン押下  private: System::Void btn_Click(System::Object^ sender, System::EventArgs^ e) {   backgroundWorker1->RunWorkerAsync();  }  // ワーカ  private: System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {   mMain->func();    } }; } ---- Main.c ---- Main::func() {  // 処理をしつつプログレスバーのValueを更新 } ----------------------------------------------------- 重たい処理をForm内で処理するのであればデリゲートを使用すれば出来そうです。 上記のようなケースでも適用できますか? また、別の方法があれば教えてください。

  • iOS4のマルチタスクについて教えてください。

    iOS4のマルチタスクについて教えてください。 iOS4のマルチタスクについて、ウィキペディでは以下のように記述されています。 >原則としてバックグラウンドのアプリケーションはタスク切替後にスリープ状態となり、 >次回呼出時に切替直前の動作状態が復元されるが、 >アップルが許可するバックグラウンド動作に関するAPIを使用することで、 >オーディオ再生やVoIP、位置情報通知などiOSの一部機能を >バックグラウンドのアプリケーションからも利用可能となる。 オーディオ再生等以外に、フォアグラウンドのアプリがコピーしたテキストの内容を、バックグラウンドのアプリが取得することは可能でしょうか? ご存知の方がいらっしゃいましたら教えてください。 よろしくお願いします。

  • [C#]FormクラスのShowメソッドの挙動について

    C#のSystem.Windows.Forms.FormクラスのShowメソッドについて調べています。 Showメソッドを使うことで、モードレスでフォームを表示できます。 http://msdn2.microsoft.com/ja-jp/library/39wcs2dh.aspx 例えば、ボタンがクリックされたときに、モードレスでフォームを表示する場合は、以下のようになると思います。 // ボタンがクリックされたときにコールされるメソッド private void button1_Click(object sender, EventArgs e) { MyForm form = new MyForm(); // MyFormはFormの継承クラス form.Show(); } このとき、button1_Clickメソッドが終了しても、 つまり、変数formのスコープから処理が外れても、MyFormは表示され続けます。 別スレッドで表示しているのかと思いましたが、MyFormを表示してもスレッド数は変わりませんでした。 なぜ、変数formのスコープから処理が外れても、MyFormが表示され続けるのかわかりません。 どなたかご存知の方がいらっしゃいましたら、ご教授いただけると幸いです。 環境 : WindowsXP SP2, .NET Framework 2.0, Visual Studio 2005

  • Thread のターゲット切り替えについて

    以下のようなソースを書きました。Runnableを実装しているクラスをスーパークラスに持つクラスThreadSampleChildをインスタンス化した後にそのクラスのThreadを実行し、途中で親クラスのスレッドに切り替えることを目的としているのですが、切り替わらずに子クラスのThreadが引き続き継続してしまいます。 理由はなんとなくわかるのですが。子クラスから親クラスのThreadを実行させるためにはどう工夫すればよいのでしょうか? class ThreadSample implements Runnable { Thread threadp; ThreadSample() { } public void run() { while(true) { try { System.out.println("Parent"); Thread.sleep(500); } catch(Exception e) { break; } } } public void makingThreadParent() { threadp = new Thread(this); } } class ThreadSampleChild extends ThreadSample { Thread threadc; ThreadSampleChild() { } public void run() { while(true) { try { System.out.println("Child"); Thread.sleep(500); } catch(Exception e) { break; } } } public void makingThreadChild() { threadc = new Thread(this); } public void exe() { while(true) { threadc.start(); try { Thread.sleep(10000); } catch(Exception e) { } threadc.interrupt(); makingThreadParent(); System.out.println("Thread Change !!!!"); threadp.start(); try { Thread.sleep(10000); } catch(Exception e) { } threadp.interrupt(); } } public static void main(String args[]) { ThreadSampleChild tsc = new ThreadSampleChild(); tsc.makingThreadChild(); tsc.exe(); } }

    • ベストアンサー
    • Java
  • iOSでシステム起動時に実行

    こんにちは。 iOSで位置情報を使用してバックグラウンドで動作するアプリを開発しようとしています。 いまのところ、バックグラウンドで実行するためには、一度フォアグラウンドで実行する必要があるのですが、一度、システムをシャットダウンしてしまいますと、改めてフォアグラウンドで実行する必要があります。 ここで、シャットダウンされても、次の起動時にバックグラウンドでの実行が継続できるようななにかうまい方法はありませんでしょうか? Appleですので、禁止されているという可能性もあると思います。その場合はそんな情報でも構いません。 よろしくお願いします。

  • スレッドの優先度を下げる方法。

    現在バックグラウンドでファイルアクセスを行うプログラムを組んでおります。 しかしこの読み込みのスレッドのCPU占有率が高いためか、バックグラウンドで 読み込んでいるのに関らず、その他の処理が重くなってしまいます。 この問題を解決しようとファイルアクセスの合間にSleepを挟みましたが 一度にファイルアクセスしている時間が長いためかあまり効果が目に見えません。 できたら平均的に負荷がかかるようにしたいのです。 何か解決方法はないでしょうか? 今考えていることは次の二つ(三つ)です。 1.ファイルアクセスを分割して負荷を下げる。 2.何らかの方法でスレッドの優先順位を下げる。 (3.ファイルアクセス自体の負荷を下げる???) 1が一番現実的かと思っています。 2の方法はプロセスの優先度を下げるソフトを目にしたことがあったので 思いついたのですが、そのような関数が今のところ見当たりません。 3は、そういうものがあるのだろうか?というレベルです。 もしあったら積極的に使いたいと思います。 できたら2の方法で解決したいと思っております。 これに関して何かご存知の方がいらっしゃいましたら、ご教授よろしくお願いします。 VC9+XP sp3にてプログラミングを行っております。

  • C# のスレッドに、上位から値を渡すには?

    いつもいつもお世話になっています。 ある装置を制御するためのプログラムをC#で作っています。 装置の状態を保持したり制御するために、下のようなクラスを作りました。 制御のためのコマンドの送受信はUDPを利用して、 その部分をスレッドにしてみました。 上位からコマンドをスレッドに渡せば制御できるかな、と思ったのですが、 スレッドにコマンドを渡す方法が分かりません。  Device dev = new Device;  dev.Start(); // スレッドが起動    :  dev.Control(1); // コマンドとして 1 を与える これで、1をスレッドに渡すには、どのようにすればいいのでしょうか? むかし、MFC C++ を少しかじったことがあるのですが、 そのときは、コマンド領域のポインタをスレッドに渡し、 スレッドの中からその領域を参照していました。 C#ではどのようにするのが普通でしょうか? よろしくお願いします。 (抜粋)  class Device  {    // 装置運転開始    public void Start() {      ComThread comThread = new ComThread();      comThread.Start();    }    class ComThread    {      public void Start()        var udpThread = Task.Factory.StartNew(()=>UDPThread());      }      public void Stop()        // スレッド停止処理      }      public void Control(int cmd)        // スレッドにコマンドを通知        cmd に入っている値をスレッドに渡したい      }      static void UDPThread()      {        for (;;) {          if (...) {  ← 上位から何らかの値を渡す必要            // コマンド送信            制御コマンド送信~レスポンス受信          }          Thread.Sleep(1000);        }      }    }  } 余談ですが、AJAXとか独立したカテゴリなのに、 C#はその他なんですね。(^ ^)

  • VBで新しいスレッド

    VBのタイマーコントロールでリストの表示の更新を制御しているのですが、どうも重いので違うスレッドにしてスレッドの優先度を低くしようかと考えました。 しかしCreateThreadでスレッドを作成しようと思っても、必ず強制終了になってしまいます。 おそらくVBが複雑な変数管理構造を採っているからだと思います。 なんでもいいから新しいスレッドを作成する方法があったら教えてください。

  • extendsの使い方

    public class ThreadSample3 { public static void main(String[] args) { ThreadA ta = new ThreadA(); ThreadB tb = new ThreadB(); ta.start(); tb.start(); } } class ThreadA extends Thread { public void run() { try { for(int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("ThreadA"); } } catch (InterruptedException e) { } } } class ThreadB extends Thread { public void run() { try { for(int i = 0; i < 10; i++) { Thread.sleep(2000); System.out.println("ThreadB"); } } catch (InterruptedException e) { } } } これは、ThreadAとThreadBを10回ずつ表示させるプログラムなのですが、extendsは子供と親の関係に当たり、例えば親クラスボールだったら子クラスが野球ボールやゴルフボールになると習いました。 class ThreadA extends Thread{ の部分はThreadとThreadAが親子関係になっていますか? またどうして子クラスの名前と親クラスの名前はこう書かないといけないですか。 

    • ベストアンサー
    • Java

専門家に質問してみよう