- PR -

高品質な進行状況ダイアログを作成するには?

投稿者投稿内容
蓮華
常連さん
会議室デビュー日: 2004/11/06
投稿数: 25
投稿日時: 2006-02-11 18:47
いつも興味深く、拝見させて頂いております。

さて、掲題の件ですが、@IT .NET TIPSで
『時間がかかる処理の進行状況をダイアログで表示するには?』で紹介されているように、
処理に時間が掛かる場合に、進行状況を表示するダイアログを作成しています。

基本的には上記の記事を参考にしている訳ですが、
このダイアログでは、進行状況ダイアログのタイトルバーをドラッグするなどすると、
進行状況のダイアログが止まってしまいます。(つまり時間の掛かる処理自体も止まります)

もちろん、マウスボタンを離して、ドラッグ操作を止めれば処理が再開されますが、
こういった場合に処理を停止させないようにする方法は無いものでしょうか?

[ メッセージ編集済み 編集者: 蓮華 編集日時 2006-02-11 18:48 ]
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2006-02-11 19:56
重い処理にはやはりスレッドを使用するのが正道ではないでしょうか。
WinFormsではスレッドを使用する場合コントロールとのメッセージのやりとりにInvoke/BeginInvokeメソッドを注意深く使用する必要がありますが、これは.NET 2.0で用意されたBackgroundWorkerクラスを使用すれば労力が軽減されます。
蓮華
常連さん
会議室デビュー日: 2004/11/06
投稿数: 25
投稿日時: 2006-02-11 20:03
返答ありがとうございます。

スレッドの件ですが、同じく@ITでの
『Windowsフォームで別スレッドからコントロールを操作するには?』
を参考にして、スレッドにて時間の掛かる処理を記述し、
そこからInvokeにてデリゲートを使用して画面のプログレスバーを
操作するようにしてみましたが、やはり同様に画面のタイトルバーを
ドラッグするなどすると、処理が止まってしまいました。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2006-02-11 20:25
引用:

蓮華さんの書き込み (2006-02-11 20:03) より:
返答ありがとうございます。

スレッドの件ですが、同じく@ITでの
『Windowsフォームで別スレッドからコントロールを操作するには?』
を参考にして、スレッドにて時間の掛かる処理を記述し、
そこからInvokeにてデリゲートを使用して画面のプログレスバーを
操作するようにしてみましたが、やはり同様に画面のタイトルバーを
ドラッグするなどすると、処理が止まってしまいました。


とりあずそれに関しては、InvokeではなくBeginInvokeを使ってみたらいかがでせう。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-11 20:26
引用:

蓮華さんの書き込み (2006-02-11 18:47) より:

(つまり時間の掛かる処理自体も止まります)


必ずしも「つまり」になるんでしょうか?

そもそも、時間のかかる処理自体はどこで実装して、
いつ PerformStep メソッドを呼び出していますか?
スレッドを使っているのであれば、そのあたりも。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2006-02-11 20:29
処理用のスレッドと表示用のスレッド同じになっていませんか?
DoEvents で回避してみるっていう手もありますが 
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-12 01:22
それ以外の回避方法...

  フォームを移動できないようにする

手軽にやるならば、フォームを移動できなくすればいいわけですがw

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2006-02-12 09:57
というか、再現しませんね。

コード:

public partial class WaitForm : Form {
	public WaitForm() {
		InitializeComponent();
	}

	public void ProcessWorks(IWin32Window owner) {
		MethodInvoker invoker = delegate {
			for(int i = 0;i < 10;i++) {
				System.Threading.Thread.Sleep(1000);
				this.Invoke(new MethodInvoker(delegate {
					progressBar.PerformStep();
				}));
			}
			this.Invoke(new MethodInvoker(delegate {
				this.DialogResult = DialogResult.OK;
			}));
		};
		invoker.BeginInvoke(delegate(IAsyncResult r) {
			invoker.EndInvoke(r);
		}, null);
		this.ShowDialog(owner);
	}
}



こんなの書いてやってみましたけど(めんどくさいのでDelegate.BeginInvoke使っているけどきちんとThread使おうね)、ウィンドウを移動していようが勝手に進みます。ただ、移動中はWindowが閉じないようですが。メッセージループを停止させているわけではないので当然ですけど。

やっぱりどこかコードが間違っているんじゃないですかね。

スキルアップ/キャリアアップ(JOB@IT)