• ベストアンサー

タスクバーに表示される文字を更新したい!

いつもお世話になっております! C#.NetでWindows Formアプリケーションを作成しております。 別Threadにて処理をしている進捗状況(%)を、Form.Textに表示更新しているのですが、フォームのタイトルバーは更新されますが、タスクバーの表示文字列がフォームを最小化などを行わないと更新されません。 タスクバーの文字列をアプリケーション側から更新する事ができるのでしょうか? ご回答よろしくお願いします。

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

  • ベストアンサー
  • luka3
  • ベストアンサー率72% (424/585)
回答No.4

こちらでも症状が再現できました。 いろいろ手がかりを探っているうちに、海外でやっと似たような質問に出会いました。 (当初から海外は調べていたのですが検索ワードがうまくはまらなかった) ・c# - How to force a redraw of my application's entry in the taskbar? - Stack Overflow http://stackoverflow.com/questions/380380/how-to-force-a-redraw-of-my-applications-entry-in-the-taskbar これをざっと見たところ、 「ウインドウタイトルが100ミリ秒以下で更新されるとタスクバーには反映されない」 というニュアンスのようです。 これをヒントにNo.3のプログラムをこのようにしてみました。 for (int i = 1; i <= 100000; i++) {  SetText((i/10000).ToString() + ":" + msg);  //System.Threading.Thread.Sleep(1000); } たくさんのループで毎回タイトルを書き換えるけども、実質10種類だけ、というものです。 こうすることでタイトルの変化に間隔が生まれタスクバーにもすべて反映されました。 こうしたことから私の考える回避策は ・毎回更新せず、時刻をミリ秒で取得して、ある程度の間隔があいてから更新するようにする ・タイマーを利用して一定間隔で更新するようにし、スレッドではタイトル文字列をどこかに保存するのみとする ・タスクバーにWM_PAINTを送ってみる? といったところですね。 ちなみに、スレッド\非スレッドでの確認のためThread...Start()を使わずに 直接ThreadTestを呼び出してみたら処理速度が体感で10倍くらい違いました。 Invokeが遅いのかな?

kamepanman
質問者

お礼

ありがとうございます! リンク先を見ると、同じような流れの回答でちょっと笑いましたw 更新が頻繁すぎるとタスクバーの更新を諦めるということですね。 回避策のうち一番処理が早いのを採用してみます。 よくよく考えると、100ミリ秒ほどの高速でタスクバーを更新する必要なんてありませんね(汗 >ちなみに、スレッド\非スレッドでの確認のためThread...Start()を使わずに >直接ThreadTestを呼び出してみたら処理速度が体感で10倍くらい違いました。 >Invokeが遅いのかな? こちらを試してみましたが、私の環境で計測してみましたが、処理速度には差がありませんでした。 ThreadTestには、this.Update();などがないのに、タイトルの表示が更新されていたのが驚きでした! いろいろと試していただいてありがとうございます! 勉強になりました!

その他の回答 (3)

  • luka3
  • ベストアンサー率72% (424/585)
回答No.3

何度もすいません。 想像で回答しても仕方が無いのでVS2010のC#をインストールしてやってみました。 結果は、新規スレッドからタイトルを変更すると即座にタスクバーへ反映されました。 テストはFormにボタンを1個置いて以下のようにしました。 WinXP SP3(32bit)とWin7 SP1(64bit)でテストしました。 private void button1_Click(object sender, EventArgs e) {  new Thread(new ThreadStart( delegate {    ThreadTest("TEST SetText");    })).Start(); } private delegate void SetTextCallback(string msg); private void SetText(string msg) {   if (this.InvokeRequired)     this.Invoke(new SetTextCallback(SetText), new object[] {msg});   else Text = msg; } private void ThreadTest(string msg) {  for (int i = 1; i <= 10; i++) {   SetText(i.ToString() + ":" + msg);   System.Threading.Thread.Sleep(1000);  }  SetText("END"); }

kamepanman
質問者

お礼

※Threadまわり書き換えなくてもいけますね。勘違いでした。 同じコードで試してみたところ、問題なく更新されました。 private void ThreadTest(string msg) {  for (int i = 1; i <= 10; i++) {   SetText(i.ToString() + ":" + msg);   System.Threading.Thread.Sleep(1000);  }  SetText("END"); } のSystem.Threading.Thread.Sleep(1000); があると更新されることも分かりました。 私の環境ですと最低でも200ミリ秒はないと、全てが反映されず、100ミリ秒で間が飛び、10程度だと1つめが更新され、次はENDが表示される状態です。 ただ、処理の量が多いので、スレッドをSleepしてしまうと、処理時間が延びてしまいます・・・。

kamepanman
質問者

補足

何度もありがとうございます!! わざわざインストールまでしていただいてスミマセン。 1TEST SetText~10TEST SetTextまでタスクバーに反映されたということでしょうか? 当方の環境がXP SP2 VS2008C#EEなので、同じコードのThreadまわりを書き換えて、試してみます!

  • luka3
  • ベストアンサー率72% (424/585)
回答No.2

先日は的外れな回答をしてすみませんでした。 タスクバーと書いてあるのに勝手にステータスバーと勘違いしていました。 ウインドウタイトルとタスクバーにずれが生じているということですよね。 ちょっと調べてみましたが似たような症状というのは見つけられませんでした。 原因として思いつくのは 「Formで作られたウインドウとは別にもう一段上に目に見えないメインウインドウがいて、  タスクバーにはこのウインドウタイトルが表示されている。  通常はForm.Textの文字列をコピーしているがスレッド処理の際は間に合っていない」 というものですが、もしこれが正しい場合の対処法は 見えないウインドウを探して、APIのSetWindowTextを呼び出すとか、 メインのDoEventsを呼びだしてみるとか、ですかね。 Spy++とかでウインドウを調べてみることはできますでしょうか。

kamepanman
質問者

お礼

ありがとうございます! お礼前に、No.3の回答を頂きましたので、順序が変ですがw 目に見えないメインウインドウが見つけられず、あまり検証できませんでした。 知識が足りず、ついて行けていない状態でした。

  • luka3
  • ベストアンサー率72% (424/585)
回答No.1

こんにちは。 C#は興味がありつつも実際にはやったことがないので 過去の経験から想像しての回答です。 ウインドウの描画の更新、といえばInvalidateです。 .NETではRefreshやUpdateもあるようですので、こちらを参考に試してみてください。 ・Refresh、Update、Invalidateメソッドの違い: .NET Tips: C#, VB.NET http://dobon.net/vb/dotnet/control/refreshupdateinvalidate.html また更新メッセージが発行されても、処理が別スレッドに取られていて処理できない、 というのも考えられますので、そういう場合はDoEventsを呼ぶといいようです。 ・EZ-NET: ステータスバーに進捗状況を表示する - Visual C# プログラミング http://program.station.ez-net.jp/special/handbook/csharp/control/StatusBar/progress.asp

kamepanman
質問者

お礼

ありがとうございます。 実際にフォームタイトルの更新は、 this.Invoke((MethodInvoker)delegate() { this.Text = str; this.Update(); }); としていますので、フォーム自体は更新されています。 DoEvents は同一スレッドでの話ではないでしょうか?

関連するQ&A