プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

BitmapCacheを指定したWPFアプリが応答しないことがあったりなかったり

という現象にはまっています

ググると9年前にstack overflowに同様の質問があったのでリンクは貼っておきます

stackoverflow.com

上記質問でも解決方法は示されていません

再現方法

UACの確認ダイアログが出るようにしておきます

f:id:puni-o:20200323144847p:plain

WPFアプリを準備します

今回は.NET Framework 4.8で作っています(Coreでも同様です)

以下にプロジェクトを置いておきます

github.com

アプリではMainWindow(プロジェクトのテンプレートで作られるやつ)のLoad時にSubWindow(プロジェクトにWindowを一つ追加)を表示してMainWindowは隠します

MainWindow.xaml.cs

public MainWindow()
{
    InitializeComponent();
    this.Loaded += MainWindow_Loaded;
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    var subWindow = new SubWindow();
    subWindow.Closed += SubWindow_Closed;
    subWindow.Show();
    this.Visibility = Visibility.Collapsed;
}

private void SubWindow_Closed(object sender, EventArgs e) => this.Close();

SubWindowでは描画処理が動いていることを確認するために1秒周期で現在時刻を更新しています。そしてこのSubWindowのコンテンツ(Grid)にBitmapCacheを指定しておきます

SubWindow.xaml

<Grid>
    <Grid.CacheMode>
        <BitmapCache/>
    </Grid.CacheMode>
    <TextBlock x:Name="Time"/>
</Grid>

SubWindow.xaml.cs

public SubWindow()
{
    InitializeComponent();
    this.Loaded += SubWindow_Loaded;
}

private void SubWindow_Loaded(object sender, RoutedEventArgs e)
{
    ThreadPool.QueueUserWorkItem(_ =>
    {
        while (true)
        {
            Thread.Sleep(1000);
            Dispatcher.BeginInvoke(new Action(() => Time.Text = DateTime.Now.ToString()));
        }
    });
}

アプリを実行するとSubWindowだけが表示されます

UACの確認ダイアログを出す

この状態で管理者権限で立ち上がるもの(管理者モードのPowerShellやタスクマネージャーなど)を起動して確認ダイアログを表示します

再描画しなくなる

SubWindowの描画が止まっていることに気づきます。タスクマネージャーで見るとCPU使用率が異常に高くなっていることがわかります(多分コア一つ占有)

f:id:puni-o:20200323150218p:plain

描画はされていませんがイベント等は動くのでアプリの終了なんかはできます

おまけ

上の例ではMainWindowを隠していますがShowInTaskbar = false;だけでも現象は発生します(ってリンク先のstack overflowにも書いてあったし実際そうなった)

おまけ 2

すべての環境で現象が発生するわけではなさそうです

おまけ 3

現象発生中に画面の解像度やスケールを変更すると復活します

まとめ

今のところMainWindowを隠す時はBitmapCacheは指定しないようにする、という対処療法みたいなことしかできません。 (MaterialDesignColors https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit のスタイルを適用するとBitmapCacheが付いてくるぞ!)

私にはこれ以上の調査は無理です、だれかエロい人おしえて