| 2019/10/08(Tue) 19:43:03 編集(投稿者)
■No92577 (大谷刑部 さん) に返信 > なので、sleepとプロパティーの設定だけだと肉眼で確認する前に次の色に変わっているという現象になっていると想像されます。
いいえ。イベント処理中は、そもそもメッセージループが処理されないので、 肉眼でも心眼でも変化しません。背景色が実際に変わるのは、 イベントを抜けた後(のアイドル時)になります。
Click イベントの最中に強制的に再描画させたいのであれば、 BackColor の変更後に Update メソッドを呼ぶなどの処置が必要です。
// ListBox と Button を貼り、 // Button の Click イベントを割り当てておきます public partial class Form1 : Form { public Form1() { InitializeComponent(); Controls.Add(editBox1 = new EditBox(listBox1) { Name = "editBox1" }); }
private void button1_Click(object sender, EventArgs e) { listBox1.Items.Insert(0, "==> button1_Click"); for (int i = 0; i <= 255; i++) { editBox1.BackColor = Color.FromArgb(i, i, i); // editBox1.Update(); } listBox1.Items.Insert(0, "<== button1_Click"); }
// TextBox に届く Windows Message を捉えて表示する実験 private EditBox editBox1; private class EditBox : TextBox { private ListBox listBox1; public EditBox(ListBox listBox1) { this.listBox1 = listBox1; }
private int Count = 0; protected override void WndProc(ref Message m) { // 受信したメッセージを、親フォームの ListBox に表示 listBox1.Items.Insert(0, ++Count + "\t" + m.ToString()); base.WndProc(ref m); } } }
> ただまあ、この程度の処理(白⇔黒)であれば、メモリ負荷とかに > それほどクリティカルな影響はないのforループでもいいんじゃないでしょうか?
『await Task.Delay(100);』とかであればいざ知らず、元の処理は 『Thread.Sleep(100);』を使っている点が問題になるかと思います。
OS にとってのメモリ負荷や CPU 負荷が軽微であったとしても、 元のコードだと 256 × 100msec なのですから、Click するだけで 25 秒以上も自アプリが待機状態(フリーズ状態)になりますよね…?
そもそも Sleep を実施している間、画面の再描画も行われないため、 このような待ち合わせ方法には、あまり意味が無いでしょう。
Sleep はスレッドの動作を一時的に止めてしまうため、 先のループ処理の間、キーボード入力やフォームの移動はおろか、 OS の再起動要求も受けられないことになるわけで、 Windows App の実装方法としては、かなり問題があるかと思います。
Sleep メソッドのリファレンスより引用: > このメソッドは、標準 COM/SendMessage ポンピングを実行しません。 Sleep API のリファレンスより引用: > Sleep 関数と、ウィンドウを直接的または間接的に作成するコードを組み合わせて > 使う場合は、注意が必要です。1 つのスレッドがウィンドウを作成した場合、 > そのスレッドはそのウィンドウに関係するメッセージを処理しなければなりません。 > また、メッセージのブロードキャスト(同報送信)が発生した場合、 > システム内のすべてのウィンドウへそのメッセージが送信されます。
ウィンドウメッセージを受け取らないスレッド (コンソールアプリやワーカースレッド等)であれば、 Sleep メソッドで待機しても問題ありません。 |