2009-04-02 18 views
1

プログラムのUIを作成していますが、変換ボタンがクリックされた後にプログレスバーが表示されない理由がわかりません。C#Winforms関数のtoolStripを更新する方法

private void convertButton_Click(object sender, EventArgs e) 
{ 
    toolStripProgressBar.Visible = true; 

    ... 

    toolStripProgressBar.Visible = false; 
} 

私はPythonでTkinterのと同様の問題に遭遇した、と私はアイドルタスクを更新する関数を呼び出す必要がありました。スレッドを使用せずにWindowsフォームでこれを行う方法はありますか?

編集:サイドノートでは、これはステータスバーのテキストで更新されるラベルを含むtoolStripのプログレスバーです。左側のラベルを取得する方法はありますか?左側のラベルを取得する方法はありますか?

答えて

4

まあ、そこスレッド(Application.DoEvents)を使用せずにこれを行う方法ですが、私は強くはそれを使ってあなたに対してお勧めします。再入門は厄介であり、あなたは本当にUIスレッドを結びつけたくはありません。

代わりにBackgroundWorkerを使用してください。これは簡単です。進捗バーには、がデザインされています。です。それは、別のスレッドを使用し、進行状況をUIスレッドに報告するという面倒を取り除きます。 Control.Invokeなどの必要はありません - それはあなたのためにそれを世話します。

lots of tutorials for BackgroundWorkerがあります。あまりにも時間がかかりすぎてはなりません。

+0

長時間実行しているプロセスを別のスレッドに移動して、常に使用可能なUIを維持することをお勧めしますか? –

+0

はい、それはBackgroundWorkerが簡単にするものです。 –

+0

ヘルプをよろしくお願いします。私はスレッドを避けることを望んでいました。なぜなら、それらは手作業ではかなり難しく、これは単純なUIですが、これは完璧と思われます。ありがとう。 –

1

スレッドなしでこれを行う方法について質問したところ、Application.DoEvents();でそれを行うことです。 (進行状況バーを表示するように設定した直後にその呼び出しを追加してください)

Jon Skeetには同意しますが、BackgroundWorkerはこれを実行するより良い方法ですが、別のスレッドを使用します。

1

プロセスをUIスレッドとは別のスレッドで実行し、そのプロセスが進行中のUIスレッドに定期的に戻す必要があります。変換操作がUIスレッド内で行われている場合、操作が完了するまでは変換されません。

1

私は、あなたのコードの"..."が長時間実行されるプロセスであるということを推測しています。 UIの更新は瞬間的ではありませんが、ウィンドウ内のメッセージキューを介して実行し、画面にペイントする必要があります。キューはポンピングされ、ペイントはイベントと同じスレッドで行われます。

結果として、長時間実行されるタスクは別のスレッドに移動する必要があります。それよりも、スレッドの終了後にコードのライン行を呼び出す必要があります。それ以外の場合は、進行状況バーを設定してすぐに再度オフにします。

これを行うには、BackgroundWorkerコントロールを使用する方法があります。

1

プログレスバーは、メッセージの処理中に発生するペイントが許可されている場合にのみ表示されます。メッセージ処理は、通常、イベントハンドラの途中では実行できません。プログレスバーが表示されるようにするには、visiblitityをtrueに設定し、バックグラウンドスレッドを開始して作業を完了し、ハンドラから戻る必要があります。ここで

1

は、物事の仕組みあなたを説明しようとする二つのリンクに行く:今 (1)(2)

を、私はすぐに私ができるようにそれを説明しようとします。 Windowsフォームアプリケーションの中で起きることのほとんどは、通常は同じスレッドMain()が実行されます。Program.csを開くと、Main()に次のような行が表示されます。

Application.Run(new Form1()); 

いつでもアプリケーションをデバッグしてコールスタックを調べると、そのRunメソッドにトレースされることがわかります。これは、Windows Formsアプリケーションが実際にはRunメソッドの連続実行であることを意味します。 Runは何をしていますか? Runは、Windowsがメッセージを送信するメッセージキューを使用しています。実行した後、それらのメッセージを正しいコントロールに送ります。それ自体は、押されているキーに対応するテキストを追加したり、再描画したりします。これはすべて単一のスレッドと同時に実行されるエンドレスループです。または単純にウィンドウを移動すると、それらのメッセージのロードがアプリケーションに渡され、アプリケーションがそのスレッドを処理してそれに応じて反応します。コントロールはキューを介して自分自身にメッセージを送信することもでき、Control.BeginInvoke経由でポンプにメッセージを配置することもできます。これらのコントロールが行うことの1つは、何が起こるかに応じてイベントを発生させることです。したがって、ボタンをクリックすると、そのクリックを処理するために作成したコードは、最終的かつ間接的にApplication.Runメソッドによって実行されます。

コードでは、進行状況バーの可視状態を可視に変更して値を更新しても、同じ方法で可視性をfalseに変更しています。つまり、メソッドを終了した後でも、Application.Run()はメッセージキューの反復処理を継続し、プログレスバーにその表示を更新するように効果的に指示します。そのようなことが起こると、メソッドを終了する前に最後に行った進捗バーの可視性を既にfalseにしています。 DoEvents()は、キュー内のメッセージを読み込んで処理するため、問題をすばやく解決する方法です。私はそれがリエントラントの問題を引き起こす可能性があるので、実際にそれを使うのが快適ではないと感じています。

スレッドを使用することは良い解決策ですが、この種の状況ではカスタムスレッドの代わりにThreadPoolスレッドを使用することをお勧めします。長寿命スレッドの数が限られている場合にのみカスタムスレッドを使用する傾向があります。私は彼らのライフサイクルをコントロールする必要があります。スレッドを使用する最も簡単で実用的な方法は、実際に何が起こっているのかを本当に理解したい場合は、デリゲートでWindows Formsマルチスレッドを実行する方法を理解することが苦労することをお勧めしますが、BackgroundWorkerコンポーネントを使用することです。

+0

故障のためにありがとう。 BackgroundWorkerソリューションが機能しましたが、今後は代理人を検討します。 –

0

私の解決方法は、ステータスストリップでリフレッシュを呼び出すことです。
これは、UIスレッドがステータスストリップを再描画すると考えています。

toolStripStatusBar1.PerformStep(); 
statusStrip1.Refresh(); 

これは.NET 4.0用です。この質問は古いですが、私はこの問題をグーグルで見つけたのは初めてです。

関連する問題