UI スレッドをフリーズしているsleeping on UI thread
ため、UI の更新が表示されません。
コントロールの再描画は UI ディスパッチャーによって行われますが、ディスパッチャーはタスクに設定された優先度に基づいて操作を実行します。コントロールの再描画は、Render に設定されたディスパッチャの優先順位で行われます。ボタンのコンテンツの設定は、優先度のレンダリングでディスパッチャーのキューに入れられますが、優先度の高いすべてのタスクが完了するまで実行されません。
他の人が示唆しているように、実行時間の長いタスクを別のスレッドに移動する必要がありますが、UI スレッドでスリープする前に GUI を更新する別の回避策があります。前述のように、UI はすべてのタスクDispatcherPriority.Render
が完了すると再描画されます。だから、あなたができることは、次のタスクに移動before sleeping on thread enqueue an empty delegate with render priority synchronously
する前にどれにするかです。force dispatcher to perform all tasks above and with priority render
これは私が意味したものです -
private void button3_Click(object sender, RoutedEventArgs e)
{
button3.Content = "Printing...";
button3.IsEnabled = false;
Dispatcher.Invoke((Action)(() => { }), DispatcherPriority.Render); <-- HERE
// button3.Refresh(); <-- After having extension method on UIElement.
Thread.Sleep(1000);
button3.IsEnabled = true;
button3.Content = "Print";
}
また、このメソッドを UIElement の拡張メソッドとして持つこともできます -
public static void Refresh(this UIElement uiElement)
{
uiElement.Dispatcher.Invoke((Action)(() => { }), DispatcherPriority.Render);
}
button3.Refresh()
そして、UI スレッドでスリープする直前に呼び出します。
ただし、ディスパッチャーは次のタスクに移動する前にレンダリング優先度以上のすべてのタスクを完了するため、button3 だけでなく、UI での更新が保留されている他のすべてのコントロールも更新されるため、これには欠点もあります。
ただし、常に心に留めておいてください。UI スレッドでスリープしないでください。