为什么一个代码路径会立即显示表单而另一个不显示?

时间:2011-08-15 13:58:02

标签: c# multithreading castle-windsor

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

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

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

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

是单独的线程导致Windows不能在顶部生成表单(并且可能被Skincrafter忽略)或者可能还有其他问题吗?

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

编辑 - 代码:

这是我制作的简单重建。将System.Management添加到引用的新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设备似乎总是创建第一个后面的第二个形式。单击该按钮每次都会生成第二个表单。

我应该注意到我正在运行Windows 7。

1 个答案:

答案 0 :(得分:0)

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

如果您使用带有所有者的ShowDialog重载会怎样?

form2.ShowDialog(this);

如果这不起作用,它会强烈地引起线程问题。您是否可以尝试更改USB事件处理程序以在表单上使用Invoke