在当前活动的监视器崩溃时打开新窗口

时间:2018-03-03 23:29:26

标签: c# wpf xaml multiple-monitors

我程序的用户报告打开新窗口的按钮导致它挂起2秒然后崩溃。虽然它在我测试过的任何计算机上都没有崩溃。

即使打开像版权信息文本一样简单的窗口,也会让它崩溃。

Axiom Crash

他们的PC规格:

  • Windows 10 Pro
  • Ryzen 5 1600(6核AMD CPU)
  • Nvidia 1080 GPU
  • 32GB RAM
  • 3440x1440 monitor

这就是我打开一个窗口的方式:

打开新窗口按钮

从MainWindow按下。

    <plugin>
   <extension
         point="org.eclipse.debug.ui.launchShortcuts">
      <shortcut
            class="launcher.LaunchShortcut"
            id="launcher.shortcut2"
            label="Launcher Test"
            modes="run">
            <contextualLaunch>
            <contextLabel mode="run" label="Run Launcher" />
            <enablement>
                <with
                    variable="selection">
                    <count
                        value="1">
                    </count>
                    <iterate>
            <adapt type="org.eclipse.core.resources.IResource">
                <and>
                    <test property="org.eclipse.core.resources.name" value="Test1.java"/>
                </and>
        </adapt>
          </iterate>
                </with>
            </enablement>
        </contextualLaunch>
      </shortcut>
   </extension> 
</plugin>

新窗口XAML

private Boolean IsMyWindowOpened = false;
private void buttonMyWindow_Click(object sender, RoutedEventArgs e)
{
    // Detect which screen we're on
    var allScreens = System.Windows.Forms.Screen.AllScreens.ToList();
    var thisScreen = allScreens.SingleOrDefault(s => this.Left >= s.WorkingArea.Left && this.Left < s.WorkingArea.Right);
    if (thisScreen == null) thisScreen = allScreens.First();

    // Check if MyWindow is already open
    if (IsMyWindowOpened) return;

    // Start Window
    mywindow = new MyWindow();

    // Only allow 1 Window instance
    mywindow.ContentRendered += delegate { IsMyWindowOpened = true; };
    mywindow.Closed += delegate { IsMyWindowOpened = false; };

    // Position Relative to MainWindow
    // Keep from going off screen
    mywindow.Left = Math.Max(this.Left - mywindow.Width - 12, thisScreen.WorkingArea.Left);
    mywindow.Top = Math.Max(this.Top - 0, thisScreen.WorkingArea.Top);

    // Open Window
    mywindow.Show();
}

新窗口C Sharp

<Window x:Class="MyProgram.MyWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:System="clr-namespace:System;assembly=mscorlib" 
        xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
        Loaded="Window_Loaded" 
        Height="200" 
        Width="450" 
        ResizeMode="CanMinimize" 
        UseLayoutRounding="True"
        Icon="Resources/Images/Icons/icon.ico"
</Window>

2 个答案:

答案 0 :(得分:0)

崩溃最可能的根本原因是:

System.Windows.Forms.Screen.AllScreens.ToList()崩溃

  • 极不可能发生

可能的修复

替换过滤
var thisScreen = Screen.FromControl(this);

可能的Repro

见下文

SingleOrDefault由于某种原因崩溃或返回null

  • 第一次提到thisScreen的属性会导致 NullReferenceException ,从而导致崩溃。

可能的修复

替换过滤
var thisScreen = Screen.FromControl(this);

重要

  • 寻找在您的解决方案中执行类似操作的其他代码,并修复(如果有的话)!
  • 重新确认问题以确认修复

可能的Repro

可能是远射,但可能是相关的!

我遇到了Hyper-V,英特尔显示驱动程序和多显示器设置的组合问题,在安装Hyper-V时,显示设置中包含虚假显示器。在这种状态下,将额外的监视器与任何类型的电缆连接都不起作用(无信号)。它只会在Windows重启期间显示额外监视器上的启动微调器,然后在所有尝试中都没有信号)。

在显示设置中看起来就像是其中一张图片(即使没有连接任何额外的显示器):

Display Settings would look something like this

Or this

找一台带有基于Intel主板和英特尔显示驱动程序的计算机,并尝试通过安装Hyper-V进入所述状态。如果偶然当前版本的Hyper-V或英特尔显示驱动程序不再表现出奇怪的行为,请尝试查找可以使用的版本。

其他问题:

  • 你说“确保mywindow的一个实例”,但你实际上泄漏了实例!你永远不会取消订阅活动,所以关于表格在展示后永远存在。确保只存在myWindow EVER的一个实例是个好主意!
  • 在实际需要之前创建窗口实例(它应该在if之后)
  • 你可以在“渲染”之前设置bool为true方式,在if之后,并消除其中一个事件订阅责任:)
  • 方法“设计”可以改进

这些问题似乎没有太大可能导致您描述的崩溃。为了确保,您应该添加一些错误记录/检查以便将来更好地进行故障排除!

答案 1 :(得分:0)

Alex.C是对的。我与System.Windows.Forms.Screen.AllScreens有类似的问题。它有时只返回null。所以用var thisScreen = Screen.FromControl(this)替换代码;应该解决这个问题