BitmapCache 导致 WPF 应用程序锁定

问题描述 投票:0回答:3

场景如下:

1:我们的 WPF 应用程序启动

2:WPF 应用程序加载各种用户控件,包括一些使用 WPF 4 中新的

BitmapCache
功能的控件

3:点击 ctrl-alt-delete 或 win+l 或加载另一个需要 UAC 的应用程序

4:取消那个东西

WPF 应用程序现在没有响应,但问题出在 WPF 本身。所有后台线程上的所有应用程序逻辑都很好,您可以通过按 alt+f4 等与其交互,但是屏幕永远不会重绘

注意事项:

  • 如果此时进入调试器,没有用户代码正在运行,这都是 WPF
  • 杀死 DWM.exe 使应用程序恢复活力
  • 如果我们取出
    BitmapCache
    d 元素,它就不会锁定
  • 我制作了另一个使用 BitmapCache 的简单示例应用程序,它没有出现问题。

救命!!

c# wpf
3个回答
2
投票

经过一番努力,一位同事终于查到了这一点。

我们的应用程序最初显示一个登录窗口,然后关闭它,并显示一个主窗口。我们很久以前就发现,如果您这样做,WPF 会假定第一个窗口(登录窗口)是应用程序的主窗口,因此它会在关闭时关闭。

为了缓解这种情况,我们在任何其他窗口之前创建了一个假的离屏窗口(从未显示)。然后,WPF 假设这个假窗口是主窗口 - 它永远不会关闭,因此我们的应用程序可以按需要工作。

供参考,假窗口如下所示:

m_mainWindow = new Window { Left = int.MaxValue, Top = int.MaxValue, Width = 1, Height = 1 };
m_mainWindow.ShowInTaskbar = false;

一切都很好。一段时间后,另一位开发人员向

Show
Hide
这个假窗口添加了一些代码。

显示主窗口是导致此问题的原因。


这是完整的重现:

A:在 Visual Studio 中制作一个新的 WPF 应用程序

B:将以下代码放入

App
 中的 
App.xaml.cs

类中
public partial class App : Application
{
    Window m_mainWindow;

    public App()
    {
        m_mainWindow = new Window { Left = int.MaxValue, Top = int.MaxValue, Width = 1, Height = 1 };
        m_mainWindow.ShowInTaskbar = false;
        
        // Comment this line out and the problem goes away
        m_mainWindow.Show();
    }
}

C:在您的

BitmapCached
中放置至少一个
MainWindow.xaml
元素。这是我的

<Window x:Class="LockupRepro.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid CacheMode="BitmapCache">
        <Button Content="Look a button" />
    </Grid>
</Window>
  1. 运行这个程序(我用的是windows 7),然后按ctrl+alt+del,或者调出UAC提示。

您会看到应用程序似乎如问题中所述锁定 - 注释掉 m_mainWindow.Show 可以修复它。

更新:

经过进一步调查,它不只是显示窗口,而是ShowInTaskBar

设置为 false。如果我们不设置它,那么显示窗口将不再导致问题。

奇怪!


0
投票
似乎问题很难重现。我所能建议的就是高级调试 -

  • 确保您的堆栈跟踪浏览器“显示外部代码”(VS 中堆栈跟踪上的右键菜单)。然后在 WPF 内部找到应用程序卡住的确切位置。

  • 下一步是加载该程序集的 pdb 或者更简单 - 使用 .NET Reflector。

  • 很多的观察和思考......

  • ???

  • 利润!

    :)


0
投票
由于这个问题在大约 14 年后仍然存在,这里有一个可靠的方法来重现它。

    创建一个窗口,创建另一个窗口,在第二个窗口的任意位置或窗口本身上添加 BitmapCache。
  1. 现在锁定窗口并取消它,第二个窗口将锁定。我正在深入研究这个问题,并且可以在此处获取生成它的存储库:
  2. https://github.com/CycloneRing/WpfBitmapCacheIssue
这是我到目前为止的发现:

    似乎只有创建的第一个窗口才会收到
  • BitmapCache
    的更新
    
  • 如果您也将
  • BitmapCache
     分配给第一个窗口,问题就会消失
  • 锁定是由第二个窗口的 WM_PAINT 失败引起的,并且它会一直发送垃圾邮件,直到 BitmapCache 响应。
  • 如果您调整第一个窗口的大小或将鼠标悬停在其中的按钮上,锁定将消失。
© www.soinside.com 2019 - 2024. All rights reserved.