【问题标题】:WindowsForm MouseUp fires twice when using Process.Start()使用 Process.Start() 时 Windows 窗体 MouseUp 触发两次
【发布时间】:2017-04-04 14:31:33
【问题描述】:

在我的 Windows 窗体应用程序中,如果单击其中一个项目,我必须打开一个带有特定文件夹的新资源管理器窗口。如果我通过

打开一个新的资源管理器窗口,我现在正在监听 MouseUp 事件(因为我已经有一些需要点击坐标的命中检测)
private void listView1_MouseUp(object sender, MouseEventArgs e)
    {
        Process.Start(@"C:\");
    }

它会打开资源管理器窗口两次。它肯定与Process.Start(@"C:\"); 有关,因为当我将线路切换到正常的控制台输出时,它只执行一次。

有没有办法将事件标记为已处理或忽略第二次执行?

【问题讨论】:

  • 尝试单步执行代码,看看它是否会运行代码两次?
  • 嗨,Bali C,刚刚试过。如果我只有一个 Console.WriteLine(e.Button);我得到了两次输出。如果我在方法内部设置断点,则它只执行一次。也许焦点转移到新打开的资源管理器窗口并很快返回?但这只是猜测。
  • 嗯,奇怪。有没有试过使用 MouseClick 事件,而不是 MouseUp,只是一个想法……
  • 看起来这可能是多选属性social.msdn.microsoft.com/Forums/windows/en-US/…的错误
  • 是的,使用鼠标单击它确实有效,并且只触发一次。但是在实际应用程序中,我真的很想使用 MouseUp,因为当用户单击并在列表框中执行操作时会发生一些事情。但如果没有其他方法,那将是后备解决方案。

标签: c# wpf winforms mouseup


【解决方案1】:

这是一个重入错误,与您在代码中使用 DoEvents() 时遇到的错误非常相似。但在这种情况下,错误是内置在操作系统中的。解决这个问题的工具是资源管理器,它在这段代码中有一个非常不寻常的激活模式。当您查看 Process.Start() 的返回值时可以看到,它是 null。当 Process.Start() 没有实际启动进程时发生。

您可以通过使用仅在第二次命中的条件断点来查看正在运行的错误。启用非托管调试和符号服务器后,调用堆栈如下所示:

WindowsFormsApp1.exe!WindowsFormsApp1.Form1.listView1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) Line 19 C#
System.Windows.Forms.dll!System.Windows.Forms.Control.OnMouseUp(System.Windows.Forms.MouseEventArgs e) Line 9140    C#
System.Windows.Forms.dll!System.Windows.Forms.ListView.WndProc(ref System.Windows.Forms.Message m) Line 6298    C#
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) Line 14236  C#
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) Line 14291    C#
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) Line 780 C#
[Native to Managed Transition]  
user32.dll!__InternalCallWinProc@20()  Unknown
user32.dll!UserCallWinProcCheckWow()    Unknown
user32.dll!CallWindowProcW()    Unknown
comctl32.dll!_CallNextSubclassProc@20()    Unknown
comctl32.dll!_CallNextSubclassProc@20()    Unknown
comctl32.dll!_MasterSubclassProc@16()  Unknown
user32.dll!__InternalCallWinProc@20()  Unknown
user32.dll!UserCallWinProcCheckWow()    Unknown
user32.dll!DispatchMessageWorker()  Unknown
user32.dll!_DispatchMessageW@4()   Unknown
shell32.dll!SHProcessMessagesUntilEventsEx(struct HWND__ *,void * *,unsigned long,unsigned long,unsigned long,unsigned long)    Unknown
shell32.dll!CShellExecute::_RunThreadMaybeWait(bool)    Unknown
shell32.dll!CShellExecute::ExecuteNormal(struct _SHELLEXECUTEINFOW *)   Unknown
shell32.dll!ShellExecuteNormal(struct _SHELLEXECUTEINFOW *) Unknown
shell32.dll!_ShellExecuteExW@4()   Unknown
System.ni.dll!71db9903()    Unknown
[Frames below may be incorrect and/or missing, native debugger attempting to walk managed call stack]   
[Managed to Native Transition]  
System.dll!System.Diagnostics.ShellExecuteHelper.ShellExecuteFunction() Unknown
System.dll!System.Diagnostics.ShellExecuteHelper.ShellExecuteOnSTAThread()  Unknown
System.dll!System.Diagnostics.Process.StartWithShellExecuteEx(System.Diagnostics.ProcessStartInfo startInfo)    Unknown
System.dll!System.Diagnostics.Process.Start()   Unknown
System.dll!System.Diagnostics.Process.Start(System.Diagnostics.ProcessStartInfo startInfo)  Unknown
System.dll!System.Diagnostics.Process.Start(string fileName)    Unknown
WindowsFormsApp1.exe!WindowsFormsApp1.Form1.listView1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) Line 19 C#

SHProcessMessagesUntilEventsEx() 函数是作恶者,拼写“DoEvents”并实现“可能等待”的漫长方法,它会导致重新进入 Winforms 应用程序的调度程序循环。再次检测 MouseUp 条件并重新触发事件处理程序。

您无法修复操作系统,但解决方法是导致重入问题的事件处理程序的通用解决方法,您可以使用 BeginInvoke() 干净地延迟棘手的代码,以便它立即运行 > 事件被处理。像这样:

private void listView1_MouseUp(object sender, MouseEventArgs e) {
    this.BeginInvoke(new Action(() => {
        Process.Start(@"C:\");
    }));
}

【讨论】:

  • 非常感谢您提供深入的解释和有效的解决方案!代码现在按预期工作,我学到了一些东西;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 2020-02-14
  • 1970-01-01
  • 2011-01-29
相关资源
最近更新 更多