2012-02-09 40 views
2

小さな.NET(Windows Forms)アプリケーションを作成していますが、マルチスレッド化の権利を得ることができません。処理中にコントロールの更新を処理する方法は?

アプリケーションには非常に単純なロジックがあります。入力するパラメータ、処理を開始するボタン、および進行状況バーが表示されたメインフォームが表示されます。ユーザーがボタンをクリックすると処理が開始され、プログラムの実行中にプログレスバーが更新されます。警告/情報を表示するために処理中にMessageBoxがポップアップし、処理が終了するとMessageBoxが結果をポップアップします。かなり単純です...しかし、コントロールのアップデートを正しく処理する方法を見つけることができないようです。

まず、私はButton_Clickedイベントですべての処理を行います。これはうまくいかなかった:それは働いたが、フォームは処理中に完全に反応しなくなり、ユーザーのクリックについて全く気にしなかった。私はこれが実際にイベントを処理するために忙しかったので、他のプロセスの処理を停止していたと仮定していたので、私はマルチスレッド化に行きました。

ボタン処理イベントで私は新しいThreadを開始し、処理を行い、その後Thread.Joinを呼び出しました。 MSDNドキュメントでは、Thread.Joinについて: "スレッドとCOMとSendMessageのポンピングを続行しながらスレッドを終了するまで呼び出しスレッドをブロックする"(http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx)しかし、これはそうではないようです。Thread.Joinを呼び出した後、スレッドが終了するまで、フォームは再び応答しなくなりました。どうしてこれなの?私はJoinアイデアを捨ててすぐにイベントハンドリング機能から戻ってきました(ユーザーが同時に複数の処理を開始しないようにフォームのボタンを無効にします)が、別の問題が発生しました。実行時に、所有者ではないスレッドからコントロールを呼び出したことに不満がありました。

だから私は最終的にBackgroundWorkerと一緒に行った:私は、フォームに1を追加し、そのRunWorkerAsync()メソッドと呼ばれ、(クロススレッド制御更新の問題を回避するため)ProgressChangedイベントを発生し、メインフォームでそれを処理するためにReportProgress()を使用。私は最終的にプログレスバーを更新することができました...しかし、これは完全に非同期です:ワーカースレッドがReportProgress()(1秒でさえ)を呼び出した後、プログレスバーは実際には何らかのランダムな間隔で更新され、 。二つの例は:私は、現在の処理ステップに関するいくつかのメッセージを表示するには、ワーカースレッドからReportProgress()、その後MessageBox.Show()を呼び出す場合

  • 、私はメッセージボックスがポップアップ表示さ後を進めるプログレスバーを見ることができます。
  • 私は結果を最後にMessageBoxをポップアップさせるRunWorkerCompletedイベントがあります。プログレスバーが最後のステップをまだ満たしている間に、画面にポップアップが表示されます。

私はここで何が欠けていますか?

+0

あなたは何も見逃してしまったようです。メッセージボックスは必要ですか?あなたがそれを取り除くと、それも醜さを減少させるのでしょうか? – Kangkan

+0

はい、アプリケーションロジックは、処理中でも終了時でもそれらを要求します。もちろん、そこに 'Thread.Sleep()'を置くこともできますが、これは本当に醜いハックのように見えます... – Massimo

答えて

0

IMHOは、WinForm(およびWPF)アプリケーションで非同期を処理するのに最も良い方法はReactive Extensionsです。あなたがそれを得ると、あなたは戻ってこないでしょう。

0

Application.DoEvents()を追加して、必要なUIを更新します。

0

あなたはかなり多くのことを試みました。ここにいくつかのヒントがありますが、正しい答えではないかもしれませんが、あなたを助けることができます。

「他のスレッドからの制御を更新する」問題を解決するには、コントロールでInvokeまたはBeingInvokeコマンドを使用できます(これにはextension methodが使用されています)。

Kangkanのコメントは正当なものだと思います。MessageBoxを使用すると、モーダルでUIが更新されないため、問題に苦痛を与えているだけです。あなたはMessageBoxが適切であることを確信していますか?続行する前にユーザー入力が絶対に必要ですか?それとも、彼らに知らせるだけですか?後者の場合は、ステータスバーのようなものを使用するか、StackOverflowでシステムメッセージを使用することを検討する必要があります(すべてがアラートであれば想像してください)。

関連する問題