为什么一个代码路径会立即在顶部显示表单,而另一个代码路径则不会

本文关键字:代码 路径 表单 显示 另一个 顶部 一个 为什么 | 更新日期: 2023-09-27 18:05:31

我正在维护一个使用Castle Windsor作为框架的c# .net程序。它还使用Skincrafter来装饰窗体。

在其中,我们有检测USB设备上文件存在的功能,并产生另一种形式来处理它。当Windows引发USB事件或当用户按下强制重新检查的按钮时,软件检查文件。

当用户强制重新检查时,如果找到该文件,则该表单将出现在主表单的顶部,并由Skincrafter进行装饰。如果USB事件被触发,则生成表单,但不会出现在顶部(必须在任务栏中单击它才能看到它),并且不会由Skincrafter装饰。

检测文件的两种方法都到达同一个函数,该函数告诉程序的另一部分生成处理该文件的表单。我在调试时发现的唯一区别是,强制重新检查方法使用主线程,而USB事件方法有它自己的子线程,通过正在显示的表单。

是单独的线程,导致Windows不产生窗体在顶部(大概被Skincrafter忽略)或可能有一些其他问题?

如果需要,我可以发布代码,但是代码路径是相同的,除了调用文件检查的方法和数据是相同的。

编辑代码:

这是我生成的一个简单重构。新的WinForms项目与系统。管理层增加了参考资料。只需创建一个带有按钮的表单(FormStartPosition设置为CenterScreen),并使用以下代码:

public partial class Form1 : Form
{
    private ManagementEventWatcher _eventWatcher = null;
    int devices = 0;
    public Form1()
    {
        InitializeComponent();
            WqlEventQuery q = new WqlEventQuery();
            q.EventClassName = "__InstanceOperationEvent";
            q.WithinInterval = new TimeSpan(0, 0, 3);
            q.Condition = @"TargetInstance ISA 'Win32_USBControllerDevice' ";
            _eventWatcher = new ManagementEventWatcher(q);
            _eventWatcher.EventArrived += new EventArrivedEventHandler(UsbEventArrived);
            _eventWatcher.Start(); // Start listen for events
    }
    private void UsbEventArrived(object sender, EventArrivedEventArgs e)
    {
        if(System.Environment.GetLogicalDrives().Length - devices != 0) {
            ShowThingy();
            devices = System.Environment.GetLogicalDrives().Length;
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ShowThingy();
    }
    private void ShowThingy()
    {
        Form form2 = new Form();
        form2.Size = new Size(50, 50);
        form2.StartPosition = FormStartPosition.CenterParent;
        form2.TopMost = true;
        form2.ShowDialog();
    }
}

运行并插入USB设备,form2表单将出现在主表单后面。

这似乎不会每次都重现问题。但我第一次插入USB设备时,似乎总是在第一个设备后面创建第二个形式。每次单击按钮都会生成顶部的第二个表单。

为什么一个代码路径会立即在顶部显示表单,而另一个代码路径则不会

您没有为模态窗口设置所有者,并且默认为活动窗口(可能不是您的主窗口)。

如果使用带有所有者的ShowDialog重载会发生什么?

form2.ShowDialog(this);

如果这不起作用,那就很有可能是线程问题。您可以尝试更改USB事件处理程序,以在窗体上使用Invoke吗?