• 締切済み

C#のフォームについて

http://dobon.net/vb/dotnet/programing/progressdialog.html 上記のサイトを元にプログラムを作成したのですがうまくいきません。 ProgressDialog pd = new ProgressDialog(); //ダイアログのタイトルを設定 pd.Title = "カウントアップ"; //プログレスバーの最小値を設定 pd.Minimum = 0; //プログレスバーの最大値を設定 pd.Maximum = 10; //プログレスバーの初期値を設定 pd.Value = 0; //進行状況ダイアログを表示する pd.Show(this); //処理を開始 for (int i = 1; i <= 10; i++) { //プログレスバーの値を変更する pd.Value = i; //メッセージを変更する pd.Message = i.ToString() + "番目を処理中..."; //キャンセルされた時はループを抜ける if (pd.Canceled) break; //時間のかかる処理 //時間のかかる処理 //時間のかかる処理 } //ダイアログを閉じる pd.Close(); 上記のコードの場合、ループ毎の最初にキャンセルかどうかの条件が書かれているため、ループ処理の途中にキャンセルを押してもきかない時があります。 処理中は常にキャンセルかを監視し、押されたらすぐにキャンセルできるようにしたいのですが、どのようにしたらいいのでしょうか。

みんなの回答

回答No.2

該当サイトの一番上の注意書きにあるとおり,現在の.NET環境であればBackgroundWorkerを使うように修正してください。 http://dobon.net/vb/dotnet/programing/progressdialogbw.html キャンセルを確認するのはワーカー側の責務です。 というのは,安全に処理を中断するタイミングで中断を開始しないと, データが壊れる等の問題が起きる可能性があり, それを判断できるのは処理を実行しているワーカー側だけだからです。 キャンセルの確認の回数を増やせば,処理中断までの時間は短くなります。 どの程度の時間を許容できるかによって,キャンセルの確認回数を増やすことになるかと想います。

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

途中で中断しても問題ないような処理であれば…… //処理を開始 for (int i = 1; i <= 10; i++) {  //プログレスバーの値を変更する  pd.Value = i;  //メッセージを変更する  pd.Message = i.ToString() + "番目を処理中...";  //キャンセルされた時はループを抜ける  if (pd.Canceled)   break;  //時間のかかる処理  //キャンセルされた時はループを抜ける  if (pd.Canceled)   break;  //時間のかかる処理  //キャンセルされた時はループを抜ける  if (pd.Canceled)   break;  //時間のかかる処理 } というように、都度都度チェックするしかないかと思われます。 # それでも判定されるタイミングは「//時間のかかる処理」の処理内容次第ということになりますけど。

関連するQ&A

  • C# or VB プログレスバー

    プログレスバーで進行状況を表示する処理を入れています。 http://dobon.net/vb/dotnet/programing/progressdialog.html 上記のサイトをパクってとりあえず作ってみました。きちんとできているのですが 1つだけ問題があって try { ProgressDialog pd = new ProgressDialog(); //ダイアログのタイトルを設定 pd.Title = "カウントアップ"; //プログレスバーの最小値を設定 pd.Minimum = 0; //プログレスバーの最大値を設定 pd.Maximum = 10; //プログレスバーの初期値を設定 pd.Value = 0; //進行状況ダイアログを表示する pd.Show(this); //処理を開始 for (int i = 1; i <= 10; i++) { //プログレスバーの値を変更する pd.Value = i; //メッセージを変更する pd.Message = i.ToString() + "番目を処理中..."; //キャンセルされた時はループを抜ける if (pd.Canceled) break; //1秒間待機する(本来なら何らかの処理を行う) System.Threading.Thread.Sleep(1000); } //ダイアログを閉じる pd.Close(); } catch { MessageBox.Show("error"); } こんな感じで使い、プログレスバー表示中に例外が走るとMessageBoxがモーダレスで 表示されてしまいます。プログレスバー表示前だとモーダルのままです。 色々調べたところ原因は裏でスレッドが走っているからだと思います。たぶん・・ ところが対処法となると少々困っています。モーダルでMessageBoxを表示させたいのですが どうすればよいのでしょうか?教えてください。

  • [C#.net]スレッド化された別フォームのプログレスバーの操作方法について

    こんちは。最近C#をやり始めて行き詰まったので質問致します。 質問内容に対する答えをお持ちの方がいらっしゃいましたら、お暇な時にでもお答えください。 public Class SumLoop { public Keisan(int Cnt, string Msg) {   // (1)プログレスバーのフォーム生成時に変数Cntをプログレスバーの最大値、変数Msgをフォームのタイトルに設定したい。   FormProgress FrmPro = new FormProgress();  Thread thread = new Thread(new ThreadStart((2)) );   thread.Start();   for(int i=0; i<Cnt; i++) {   // (3)このiがインクリメントする度にプログレスバーのValueを増やしたい   // FrmPro.SetProgressValue(i) // これだとコンパイラに怒られた    // ここに主な処理   } } public partial class FormProgress : System.Windows.Forms.Form {  public FormDfmProgress() { InitializeComponent(); }  // (3)これではダメみたい  public void SetprogressValue(int iValue) {   progressBar1.Value = iValue;   progressBar1.Refresh();  }  // (4)他のイベントが必要? } ざっと汚いコードを書きましたが具体的にお知恵を貸して頂きたいところは (1)のフォーム生成時のパラメータをどう与えるのか? インスタンス作成の際にここで言うFormDfmProgressをthisで継承させオーバーロードさせれば良いんでしょうか? (2)プログレスバーのフォームを表示させたいだけなのですが、.ShowDialog()では怒られ、.Showでは即座にフォームが消えたりでどうにもなりません。スレッドが消えるまで表示させるにはどうしたらいいでしょう? (3)フォーム側のプログレスバーのValueなり、変数なりをスレッド稼動中に更新させるにはどうしたらいいでしょうか? (4)は、大して気にしていないのですが、これが致命的に足りない!とかいうのがあればご指導願います。 以上長々となりましたが、お暇な方お力を御貸しください

  • C#メッセージボックスバックグラウンド

    時間のかかる処理でユーザーが他のボタンを触らないよう、 メッセージボックスをモーダルで出すにはどうすれば良いでしょうか。 普通に出すと、処理がそこで止まってしまいます。 プログレスバーは特に必要ありません。なるべく簡単な方法でお願いします。

  • プログレスバーについて

    サーバー上からファイルをダウンロードするアプリを 作成しているものです。 ClassAとClassBが存在するとして、 ClassAでファイルをダウンロードする処理を記述し、 ClassBでプログレスバーを含むダイアログを作成しています。 ClassAのファイル読み込みのループ処理のカウンターを プログレスバーのメンバー変数m_plgと同調させたい。 例 ClassA  for(i=0;i<count;i++){  } ClassB  m_plg.SetRange(0,count); m_plg.SetPos(i); かなり簡略化してます。 上記内容は実現可能だと思うのですが、メンバー変数の宣言部がおかしいのか m_plgは宣言されていませんとエラーがでます。 メンバー変数の理解不足だと思うのですが、このような処理を行いたい場合は どちらのClassにも認識されるようなコントロールのメンバー変数はどのようにして 宣言すればよろしいのでしょうか? 開発環境はVC++6.0 MFC ダイアログです。

  • vc++2008の進行状況ダイアログ表示に関して

    現在VC++2008にて開発を行っております、C++初心者の者です。 モーダルダイアログを表示し、 そのダイアログの値を利用・表示した進行状況ダイアログを表示したいと考えています。 ・進行状況ダイアログに表示する値  現在作成ファイル数 / 総制作ファイル数  (プログレスバーの表示は考えていません。) ・現在、進行状況ダイアログはモーダレスダイアログを表示し、表示している値をforループ内で変更するような処理にしていますが、ダイアログには何も表示していません。 どのような処理にすればよろしいでしょうか。 宜しくお願いします。

  • EXCEL VBA フォームコード簡素化

    EXCEL VBAのフォームにテキストボックスを複数作成しております。 下記のように複数のテキストボックスで同じ処理を行うのですが コントロール→ループか何かで簡素化できないでしょうか? Private Sub TextBox17_Exit(ByVal Cancel As MSForms.ReturnBoolean) TextBox17.Value = Format(TextBox17.Value, "0.00") End Sub Private Sub TextBox18_Exit(ByVal Cancel As MSForms.ReturnBoolean) TextBox18.Value = Format(TextBox18.Value, "0.00") End Sub Private Sub TextBox19_Exit(ByVal Cancel As MSForms.ReturnBoolean) TextBox19.Value = Format(TextBox19.Value, "0.00") End Sub Private Sub TextBox20_Exit(ByVal Cancel As MSForms.ReturnBoolean) TextBox20.Value = Format(TextBox20.Value, "0.00") End Sub Private Sub TextBox21_Exit(ByVal Cancel As MSForms.ReturnBoolean) TextBox21.Value = Format(TextBox21.Value, "0.00") End Sub Private Sub TextBox22_Exit(ByVal Cancel As MSForms.ReturnBoolean) TextBox22.Value = Format(TextBox22.Value, "0.00") End Sub 以上お力添えお願いいたします。

  • VB6 DoEventsの代わりは?

    お世話になります。 progressbarを表示するために、 重たい処理のループの中ではDoEventsを入れることで表示ができているのですが、 ループとループの間でprogressbarを更新するには、どのようにしたらよろしいでしょうか? ***** 現状 for i =1 to 9999 重い処理 Frm_ProgressBar.ProgressBar1.value = 進捗数 DoEvents next i ***** やりたいこと for i =1 to 9999 重い処理A next i Frm_ProgressBar.ProgressBar1.value = 進捗数 DoEvents for i =1 to 9999 重い処理B next i

  • 「VC++6」ウィンドウの再描画

    VC++6を使って簡単なプログラムをダイアログベース作っています。 内容はリストを読み込み、1件ずつDBにSQLを発行して情報を取得していくという内容です。 画面には、プログレスバーも設置しており、普通に操作すると正常に、プログレスバーも動きます。しかし、いったん別のウィンドウをアクティブにして、作成した動作中のプログラムを再選択しても、画面は壊れたまま再描画されません。しばらくまって、リストのSQL発行が終わって、画面に結果が表示されたら、きちんと再描画されます。 そこまで処理が終わったら、他のウィンドウに切り替えて戻ってきても画面が壊れることはありません。 時間がかかるプログラムなので、動作中に別の仕事をするため、アクティブでなくても、きちんとウィンドウを更新したいのです。 ちなみに、ループ処理中にRedrawWindow();を入れてみましたがダメでした。 アドバイスよろしくお願いします。

  • 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("キャンセルされずに終了しました"); } }

  • スレッド処理からダイアログを表示するには?

    Windows XPとVC++ 6.0で 時間のかかる大量の計算をするプログラムを作っています。 計算部分はスレッド処理にして 進捗ダイアログ(CDialogにCProgressCtrlを貼り付けたもの) を表示します。 ・CWinAppのInitInstanceで計算処理開始(AfxBeginThread) ・計算処理内で進捗ダイアログをCreate ・計算の進み具合によって進捗ダイアログのプログレスバーを更新 上記の流れではうまくいっていたのですが 以下のように変更したところ、進捗ダイアログをCreateするところで プログラムが応答なしになってしまうようになりました。 ・メインダイアログ(モーダル) ・メインダイアログのAボタンクリックでダイアログAを開く(モーダル) ・ダイアログAの実行ボタンクリックで計算処理開始(AfxBeginThread) ・計算処理内で進捗ダイアログをCreate ・計算の進み具合によって進捗ダイアログのプログレスバーを更新 MFC Wizardでダイアログベースで作成、MFCの共有DLLを使用しています。 モーダルダイアログ→スレッド→CDialog.Createに 制限があったりするのでしょうか。 どうかご教授ください。