• ベストアンサー
  • 困ってます

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(); } } }

共感・応援の気持ちを伝えよう!

  • 回答数1
  • 閲覧数603
  • ありがとう数0

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

  • ベストアンサー
  • 回答No.1
  • Wr5
  • ベストアンサー率53% (2177/4070)

>プログレスバーが終了するまえに”終了”が出てしまいますが >これはどうしてでしょうか? 単純にタイミングの問題なんじゃないですかねぇ…。 >progressBar1.Value = e2.ProgressPercentage; でプログレスバーの値が書き換わりますが、再描画の指示がメッセージキューに積まれます。 で、その再描画を処理する前にRunWorkerCompletedが処理されてしまった。 ということかと。 実行している環境のスペック次第でそこら辺は変わるかも知れません。 # というかこちらではそんな事になりませんでしたし……。 MessageBox.Show()の前にprogressBar1.Update()とか入れてみたらどうなりますかね? # まあ、このタイミングで再描画強制できるかどうかは不明ですが。 # button1.Enabled = true;でのボタンの再描画は走っているみたいですからイケますかねぇ…。 あと……テストだからいいかも知れませんが、DoWorkでResult設定した方がいいんじゃないですかね。

共感・感謝の気持ちを伝えよう!

関連するQ&A

  • BackgroundWorkerと同期 VB2008 VB2005

    VB2008で、BackgroundWorkerを使って重たい処理をさせています。 DoWork内で、ReportProgress(パーセント値)を呼び出して ProgressChangedメソッドで、そのときの状態を表示させています。ぷプログレスバーだけでなく、あらかじめ作成したデータをTextBoxに情報を表示させています。 しかし、ReportProgress(パーセント値)の後にSystem.Threading.Thread.Sleep(200)を入れないと、たまに ProgressChangedの中のTextBoxを表示させる処理が実行されなくなります。 ReportProgress(パーセント値)の後に同期をとる処理はSleep以外に何かあるのでしょうか? BackgroundWorkerの同期について詳しく書かれている本も探しています。

  • VB2005 BackgroundWorkerの使用

    お世話になります。 VB2005のBackgroundWorkerを指定した数だけ使用したいのですが エラーメッセージが以下のように表示されます。 ---------------------------------------------- BackgroundWorker は現在ビジー状態であるため、 複数のタスクを同時に実行できません。 ---------------------------------------------- コーディングは ~FormLoad~ BackgroundWorker1.RunWorkerAsync() BackgroundWorker1.RunWorkerAsync() この部分はFor文で指定しただけ実行したいと考えてます ~DoWork~ Console.Write("DoWork" & vbCrLf) ~RunWorkerCompleted~ Console.Write("RunWorkerCompleted" & vbCrLf) と、しております。 どのようなコーディングを行えば複数実行することが 可能なのでしょうか? よろしくお願いします。

  • BackgroundWorkerの処理

    マルチスレッド機能であるBackgroundWorkerを利用してプログラムを書いていたのですが DoWorkからコントロールへのアクセスが出来ません。 どうすればコントロールへアクセスできるのでしょうか? 誰かお詳しい方、ご教授願います。 Private Sub back1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles back1.DoWork     textbox1.text="処理中とか表示したい" End Sub

  • BackgroundWorker 表示の更新

    C#2010で、BackgroundWorkerを使って進行状況ダイアログを表示しています。 ProgressChangedでProgressBarの値とTextBoxのテキストを変更していますが、ProgressBarの表示がうまく更新できません。早くてはっきりとは確認できないのですが、TextBoxはその都度指定した値が表示されているようです。 QNo.4159618 にあるように、Application.DoEvents()を試しましたが、変化ありませんでした。 Sleepを入れる方法は有効なのですが、表示が更新される最短の時間だけブロックする方法はないでしょうか? もしくはProgressBarの表示をすぐさま更新することができないでしょうか? ManualResetEventというのを試してみましたが、以下の方法では、変化ありませんでした。 ・ProgressChangedでManualResetEvent.Set() ・バックグランド処理でReportProgressを呼んだ後にManualResetEventのWaitOne()とReset()

  • C# 計算

    int i = 1 / 2 * 100; という計算式をソースに書いた際 変数iには50が入ってほしいのですが… 変数iには0が入ってしまいます。 double = 1.0/2.0*100 にすれば、50になりますが、int型で解決したいと思っています。 BackgroundWorker.ReportProgressの引数にしたい為です。

  • backgroundworkerについて C#

    C# 2005で、backgroundworker1.RunWorkerAsync(100);とした場合は、 DoWorkイベントでbgWorkerArgが以下のように100になるのはわかりますが、 int bgWorkerArg = (int)e.Argument; 例えば2つの文字列を送る場合や、構造体を送ることは可能でしょうか? 簡単なサンプルがあれば助かります。 あと、DoWorkイベントの中で // senderの値はbgWorkerの値と同じ BackgroundWorker woker = (BackgroundWorker)sender; としているサンプルを見つけましたが、この後 workerは一般的に何に使うのでしょうか?サンプルでは、何も使っていませんでした。 Threadよりbackgroundworkerを使うように書かれているものも見ましたが 薦めている理由も知りたいです。

  • C# バックグランドのキャンセル方法???

    SMTP でメールを送る際に 4000KB 以上ある画像ファイルを添付しております 当然時間が掛かりますので送信部分を切り出してバックグランド化致しました 主要部分は次の通りです System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient(); smtp.Host = "smtp.MyMail.com"; string MailSubject = ""; string MailBody = ""; MailMessage oMsg = new MailMessage("○○○@○○○.com", "□□□@□□□.com", MailSubject, MailBody); oMsg.Attachments.Add(new Attachment(@"大きな画像.bmp")); smtp.Send(oMsg); でもやはり送信には時間が掛かりますのでキャンセル機能を追加いたいと思い、その方法を調べました するとバックグランドの中の重たい処理の途中で定期的にキャンセルの有無をチェックしろとあり、サンプルとして下の例が示されています このForループの中に処理を入れろと言われても送信部分は一本道です、ループの中に組込みようがありません、どうすれば良いのでしょうか? ★ それとも私は基本的な誤解をしているのでしょうか??? private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { for (int i = 0; i < 100; i++) { //処理中にキャンセルされていないかを定期的にチェックする if (this.backgroundWorker1.CancellationPending) { e.Cancel = true; return; } } } //バックグラウンド処理の終了を判断する private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { MessageBox.Show("キャンセルされました"); } else { MessageBox.Show("キャンセルされずに終了しました"); } }

  • c#のプログラムについて。

    c#のプログラムについて。 お世話になります。 c#初心者です。 下記の様なコードを記述してますが、 「 Form1.Button1.Visible == false;」の部分で 「'WindowsFormApplication1.Form1'にButton1'の定義がありません。」 と言うエラーが出てしまいます。 どの様に定義して良いのかが分からず、悩んでいます。 どなたかお教え頂きたく宜しくお願い致します。        記 using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace WindowsFormsApplication3 { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); string result = System.Environment.MachineName; if (result == "xxxxxxx") { Form1.Button1.Visible == false; } } } }

  • backgroundWorkerに無視される。。。

    C#のbackgroundWorkerがうまく動いてくれません。あるページを丸コピーしているのですが・・・(VC#2010ex、WINフォームアプリで作成を使用です) http://www.atmarkit.co.jp/fdotnet/dotnettips/436bgworker/bgworker.html こちらのページを丸ごと参考にしているのですがなぜかうんともすんとも言いません・・・ どなたか原因をご教示いただけませんでしょうか? 各コントロールのプロパティも名称を合わせました。 WorkerReportsProgressプロパティをtrueに設定にもしております。 あとは、ボタンをダブルクリックしてソースの編集画面を開き丸ごとソースをコピーしました。 それでビルドしてみたのですが・・・全く動きません(T_T;)案内通りにしたのですが ちなみにダウンロードしたやつをVS2005でやってみたところちゃんと動きました。 おそらく何か足りていないかと思うのですが、まったくエラーにもならないのでどうしたらいいか初心者にはわかりません。 ご解説いただけませんでしょうか?

  • C# フォームを閉じてもプログラムが終了しない

    前略 ・C#の初心者です。 ・下記のようなプログラムを作りたいと思っています。プログラムは<作りたいプログラム>の仕様どうりに動作していますが、Form1のFormClosingイベントに Application.Exit()を追加しないと フォーム1で "X"(閉じる)をクリックしても(フォームは非表示になりますが)プログラムが終了しません。プログラムでどこかおかしな部分があると思っています。Application.Exit()を追加しないでもプログラムを終了する方法を教えてください。 <作りたいプログラム> (1)Form1 のbutton1をクリックすると新しいForm2が作成され表示される。Form2が表示されるとForm1は非表示となる。 (2)Form2 のbutton1をクリックするとForm2が非表示となりForm1が表示される。 (3)Form1 の "X"(閉じる)をクリックしてプログラムを終了する。 //Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace formClose { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 form2 = new Form2(); form2.Show(); //フォーム2を表示 this.Hide(); //フォーム1を非表示 } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { Application.Exit(); //アプリケーション終了 } } } //Form2.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace formClose { public partial class Form2 : Form { Form1 form1 = new Form1(); public Form2() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { this.Close(); //フォーム2を閉じる } private void Form2_FormClosing(object sender, FormClosingEventArgs e) { form1.Show(); //フォーム1を表示する } } } 以上