我正在维护一个使用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。
答案 0 :(得分:0)
您没有为模态窗口设置所有者,默认为活动窗口(可能不是您的主窗口)。
如果您使用带有所有者的ShowDialog重载会怎样?
form2.ShowDialog(this);
如果这不起作用,它会强烈地引起线程问题。您是否可以尝试更改USB事件处理程序以在表单上使用Invoke?