AプロセスとBackgroundWorkerが存在します。
AプロセスはBackgroundWorkerにプログレスバー表示を依頼し、
その後、処理が完了した段階でBackgroundWorkerにプログレスバー終了依頼を出します。
このとき、
Aプロセスでは以下のようにプログレスバーの終了を待ち受けます。
while(プログレスバー表示フラグ==true){
System.Windows.Forms.Application.DoEvents();
log.write("注意:プログレスバー表示中");
}
BackgroundWorkerでBoolean型のプログレスバー表示フラグをfalseに
しているのですが、Aプロセスのループから抜けません。
BackgroundWorkerが終了したことを伝えループを終える良い解決方法はありませんか?
サンプルを作ってみました。
フォーム上にプログレスバーとボタンを配置してください
プログレスバー progressBar1
ボタン button1
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace TestThreading { public partial class Form1 : Form { private BackgroundWorker bgWorker; delegate void dlgProgress(int percentage); bool wait = false; public Form1() { InitializeComponent(); bgWorker = new BackgroundWorker(); bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); } private void button1_Click(object sender, EventArgs e) { this.progressBar1.Value = 0; this.button1.Enabled = false; bgWorker.RunWorkerAsync(); wait = true; while (wait) { Application.DoEvents(); } this.button1.Enabled = true; } void bgWorker_DoWork(object sender, DoWorkEventArgs e) { //時間のかかる処理 for (int i = 0; i < 10; i++) { System.Threading.Thread.Sleep(100); int percentage = 10 * (i + 1); progressBarUpdate(percentage); } } void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { wait = false; } /// <summary> /// プログレスバーの更新 /// </summary> public void progressBarUpdate(int percentage) { if (!(this.IsHandleCreated)) { return; } MethodInvoker process = (MethodInvoker)delegate() { if (this.progressBar1.Maximum > percentage) this.progressBar1.Value = percentage; else this.progressBar1.Value = 100; }; if (this.InvokeRequired) { this.Invoke(process); } else { process.Invoke(); } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { bgWorker.DoWork -= new DoWorkEventHandler(bgWorker_DoWork); bgWorker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); bgWorker.Dispose(); bgWorker = null; } }
}
グローバルの変数で プログレスバーが 終了したら フラグを 立てるようにする。
その変数を 質問の中のループで チェックして フラグが たってたら 抜けるようにしてやればいいでしょう。
または、そのループ内で プログレスバーが終了したか どうか(たぶん 100%)かどうかを
チェックして 終了したら 抜ければいいでしょう。
回答ありがとうございます。
現在、プログレスバーを終了するタイミングでBoolean型のプログレスバー表示フラグをfalseに
しています。このプログレスバー表示フラグはAプロセスが管理する変数なので
ともにアクセスできるグローバルなエリアにフラグを設けて確かめます。
処理は、Aプロセスで行っているのでしょうか、それともBackgroundWorkerで行っているのでしょうか?
私ならAプロセスの中に処理を組み込み、BackgroundWorkerはプログレスバーの表示に集中させます。
そしてAプロセスが終わり次第、AプロセスからBackgroundWorkerには表示を終了するよう指示させます。
つまり
while(プログレスバー表示フラグ==true){
System.Windows.Forms.Application.DoEvents();
log.write("注意:プログレスバー表示中");
処理
if(処理終了==true){ プログレスバー表示フラグ=false; }
}
プログレスバーの後片付け
という感じです。
回答ありがとうございます。
>>処理は、Aプロセスで行っているのでしょうか、それともBackgroundWorkerで行っているのでしょうか?
>>私ならAプロセスの中に処理を組み込み、BackgroundWorkerはプログレスバーの表示に集中させます。
>>そしてAプロセスが終わり次第、AプロセスからBackgroundWorkerには表示を終了するよう指示させます。
現状次のようになっています。
●Aプロセスの処理
プログレスバー終了フラグ=true; ←②
while(プログレスバー表示フラグ==true){
System.Windows.Forms.Application.DoEvents();
log.write("注意:プログレスバー表示中");←③
}
log.write("処理完了");←⑥
●BackgroundWorkerの処理
while(プログレスバー終了フラグ){
log.write("進捗表示");←①
}
プログレスバー終了←④
プログレスバー表示フラグ=true;←⑤
System.Windows.Forms.Application.DoEvents();
1~6の順序で処理が流れてほしいのですが、③のループから抜け出せません。
この原因についてもご回答いただきたいです。
ご存じかと思いますが、Windowsの場合、プロセス間の値のやり取りはレジストリを介して行います。
その「プログレスバー表示フラグ」というのはレジストリ変数になっていますか?
ご確認ください。
参考 「レジストリの値を取得するには?」
サンプルを作ってみました。
フォーム上にプログレスバーとボタンを配置してください
プログレスバー progressBar1
ボタン button1
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace TestThreading { public partial class Form1 : Form { private BackgroundWorker bgWorker; delegate void dlgProgress(int percentage); bool wait = false; public Form1() { InitializeComponent(); bgWorker = new BackgroundWorker(); bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); } private void button1_Click(object sender, EventArgs e) { this.progressBar1.Value = 0; this.button1.Enabled = false; bgWorker.RunWorkerAsync(); wait = true; while (wait) { Application.DoEvents(); } this.button1.Enabled = true; } void bgWorker_DoWork(object sender, DoWorkEventArgs e) { //時間のかかる処理 for (int i = 0; i < 10; i++) { System.Threading.Thread.Sleep(100); int percentage = 10 * (i + 1); progressBarUpdate(percentage); } } void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { wait = false; } /// <summary> /// プログレスバーの更新 /// </summary> public void progressBarUpdate(int percentage) { if (!(this.IsHandleCreated)) { return; } MethodInvoker process = (MethodInvoker)delegate() { if (this.progressBar1.Maximum > percentage) this.progressBar1.Value = percentage; else this.progressBar1.Value = 100; }; if (this.InvokeRequired) { this.Invoke(process); } else { process.Invoke(); } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { bgWorker.DoWork -= new DoWorkEventHandler(bgWorker_DoWork); bgWorker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); bgWorker.Dispose(); bgWorker = null; } }
}
回答ありがとうございます。
回答いただいたサンプルソースは大体私のソースと類似しています。
残念ながらまだ問題は解決していませんが、解ったことがございましたので
追記します。
Aプロセスで以下のようにコーディングした場合
this.progressBar1.Value = 0;
this.button1.Enabled = false;
bgWorker.RunWorkerAsync();
wait = true;
while (wait)
{
log.Write("test") ←①
Application.DoEvents();
}
①で出力しているログが1回しか記録されません。
Application.DoEventsイベント後に、While文が動いていないように
思えるのですが、いまだ原因は不明です。
なお、現状のコーディングでも10回操作すれば8回ほど
期待通りの動作をすることを確認しています。
たまに、
ループのフラグがFalseになったのにも関わらず抜け出さないことがあるようです。
ご助言宜しくお願いします。
回答ありがとうございます。
回答いただいたサンプルソースは大体私のソースと類似しています。
残念ながらまだ問題は解決していませんが、解ったことがございましたので
追記します。
Aプロセスで以下のようにコーディングした場合
this.progressBar1.Value = 0;
this.button1.Enabled = false;
bgWorker.RunWorkerAsync();
wait = true;
while (wait)
{
log.Write("test") ←①
Application.DoEvents();
}
①で出力しているログが1回しか記録されません。
Application.DoEventsイベント後に、While文が動いていないように
思えるのですが、いまだ原因は不明です。
なお、現状のコーディングでも10回操作すれば8回ほど
期待通りの動作をすることを確認しています。
たまに、
ループのフラグがFalseになったのにも関わらず抜け出さないことがあるようです。
ご助言宜しくお願いします。