为什么单击 ToolStrip 按钮两次时会引发 NullReferenceException - openFileDialog.showDialog()?

发布于 2024-10-09 23:28:11 字数 2511 浏览 8 评论 0原文

我创建了一个干净的 WindowsFormsApplication 解决方案,向主窗体添加了一个 ToolStrip,并在其上放置了一个按钮。我还添加了一个 OpenFileDialog,以便 ToolStripButtonClick 事件如下所示:

private void toolStripButton1_Click(object sender, EventArgs e)  
{  
    openFileDialog1.ShowDialog();  
}

我没有更改任何其他属性或事件。

有趣的是,当我双击 ToolStripButton 时(在对话框打开之前第二次单击必须非常快),然后取消两个对话框(或选择一个文件,这并不重要),然后单击主窗体的客户端区域,NullReferenceException 使应用程序崩溃(错误详细信息附在帖子末尾)。 请注意,Click 事件已实现,而 DoubleClick 未实现

更奇怪的是,当 OpenFileDialog 被任何用户实现的表单替换时,ToolStripButton 会阻止单击两次。

我在 Windows 7 Professional(来自 MSDNAA)上使用 VS2008 和 .NET3.5,并进行了最新更新。我没有更改 VS 中的许多选项(仅更改字体大小、工作区文件夹和行编号)。

有谁知道如何解决这个问题?它在我的机器上 100% 可复制,在其他机器上也是如此吗?

我能想到的一种解决方案是在调用 OpenFileDialog.ShowDialog() 之前禁用该按钮,然后再启用该按钮(但这不太好)。还有其他想法吗?

现在承诺的错误详细信息:

System.NullReferenceException 未处理
Message="未将对象引用设置为对象的实例。"
源=“System.Windows.Forms”
堆栈跟踪:
在 System.Windows.Forms.NativeWindow.WindowClass.Callback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)
在 System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG& msg、HandleRef hwnd、Int32 msgMin、Int32 msgMax、Int32 删除)
在System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID,Int32原因,Int32 pvLoopData)
在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 原因,ApplicationContext 上下文)
在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 原因,ApplicationContext 上下文)
在 System.Windows.Forms.Application.Run(Form mainForm)
在 WindowsFormsApplication1.Program.Main() w C:\Users\Marchewek\Desktop\Workspaces\VisualStudio\WindowsFormsApplication1\Program.cs:第 20 行
在 System.AppDomain._nExecuteAssembly(程序集,String[] args)
在 System.AppDomain.ExecuteAssembly(字符串 assemblyFile,证据 assemblySecurity,字符串 [] args)
在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
在 System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
在 System.Threading.ExecutionContext.Run(ExecutionContextexecutionContext,ContextCallback 回调,对象状态)
在 System.Threading.ThreadHelper.ThreadStart()
内部异常:

I created a clean WindowsFormsApplication solution, added a ToolStrip to the main form, and placed one button on it. I've added also an OpenFileDialog, so that the Click event of the ToolStripButton looks like the following:

private void toolStripButton1_Click(object sender, EventArgs e)  
{  
    openFileDialog1.ShowDialog();  
}

I didn't change any other properties or events.

The funny thing is that when I double-click the ToolStripButton (the second click must be quite fast, before the dialog opens), then cancel both dialogs (or choose a file, it doesn't really matter) and then click in the client area of main form, a NullReferenceException crashes the application (error details attached at the end of the post). Please note that the Click event is implemented while DoubleClick is not.

What's even more strange that when the OpenFileDialog is replaced by any user-implemented form, the ToolStripButton blocks from being clicked twice.

I'm using VS2008 with .NET3.5 on Windows 7 Professional (from MSDNAA) with latest updates. I didn't change many options in VS (only fontsize, workspace folder and line numbering).

Does anyone know how to solve this? It is 100% replicable on my machine, is it on others too?

One solution that I can think of is disabling the button before calling OpenFileDialog.ShowDialog() and then enabling the button back (but it's not nice). Any other ideas?

And now the promised error details:

System.NullReferenceException was unhandled
Message="Object reference not set to an instance of an object."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.NativeWindow.WindowClass.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG& msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at WindowsFormsApplication1.Program.Main() w C:\Users\Marchewek\Desktop\Workspaces\VisualStudio\WindowsFormsApplication1\Program.cs:line 20
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

耀眼的星火 2024-10-16 23:28:11

我能够在 Windows 7 机器上复制类似的内容 - 我没有遇到异常,但我的表单将不再重绘。可能是因为我没有在 win 7 机器上的调试器中运行,所以异常被吞掉了。

在我的 XP 机器上不会发生这种情况。仅当我使用 toolStripButton 并在第一次打开对话框时双击它时,才会发生这种情况。如果我正常打开对话框,然后先将其关闭,则双击不会打开对话框两次。

怀疑这里发生的事情类似于竞争条件 - 框架开发人员从未预料到他们的代码可以输入两次,但这种情况的发生是因为一个新的回调到消息循环中。那么为什么会发生这种情况 - 对我来说看起来像是一个错误。

我发现了一种非常简单的解决方法可以阻止它发生 - 启用 toolStripButton 的 DoubleClickEnabled 属性。您不必实现双击处理程序 - 它会将双击视为单击,然后一切正常。

我会这样处理:

    public Form1()
    {
        InitializeComponent();

        // This is a workaround for a framework bug
        // see blah blah
        toolStripButton1.DoubleClickEnabled = true; 

    }

下次升级框架时,您可以尝试删除它。

尼尔

I was able to replicate something like this on a windows 7 Machine - I don't get exception the but my form will no longer redraw. It may be that because I am not running in a debugger on the win 7 box that the exception is being swallowed.

This does not happen on my XP machine. This only happened when I used the toolStripButton and double clicked on it the first time I opened the dialog. If I opened the dialog normally and then closed it first then the double click does not open the dialog twice.

I suspect that what is happening here is similar to a race condition - where the framework developer never expected that their code could be entered twice, but that has occurred because of a new call back into the message loop. So why is this happening - looks like a bug to me.

I found one quite easy workaround that stops it from happening - enable the DoubleClickEnabled property of the toolStripButton. You don't have to implement the double click handler - it treats the double click as a single click then and it all works.

I would handle this thus:

    public Form1()
    {
        InitializeComponent();

        // This is a workaround for a framework bug
        // see blah blah
        toolStripButton1.DoubleClickEnabled = true; 

    }

Next time you upgrade frameworks you can try removing it.

Neil

琉璃梦幻 2024-10-16 23:28:11

ShowDialog 方法是模态的。通常,在调用 ShowDialog 后,OpenFileDialog 拥有应用程序的独占 UI 焦点,直到对话框关闭。

通过快速双击该按钮,您将在框架有机会给予 OpenFileDialog 独占 UI 焦点之前再次调用 ShowDialog。这使您的应用程序进入无效状态。

虽然这不应该是可能的,但显然是不可能的,现在这是你的问题。要么订阅按钮的 Click 事件,并在第一次单击后禁用该按钮;或者从设计器中删除 OpenFileDialog 并在 Click 处理程序中以编程方式创建它。如果您执行后者,请将其包装在 using 块中以确保垃圾收集:

private void toolStripButton1_Click(object sender, EventArgs e)   
{
    using(var OFD = new OpenFileDialog())
    {
        OFD.ShowDialog();  
    } 
} 

The ShowDialog method is modal. Normally after ShowDialog is called, the OpenFileDialog has the exclusive UI focus of the application until the dialog is closed.

By quickly double clicking the button you are calling ShowDialog again before the framework has had a chance to give OpenFileDialog exclusive UI focus. This has put your application into an invalid state.

Although this shouldn't be possible, clearly it is, and now it's your problem. Either subscribe to the button's Click event and disable the button after the first click; or remove the OpenFileDialog from the Designer and create it programatically in your Click handler. If you do the latter, wrap it in a using block to ensure garbage collection:

private void toolStripButton1_Click(object sender, EventArgs e)   
{
    using(var OFD = new OpenFileDialog())
    {
        OFD.ShowDialog();  
    } 
} 
情独悲 2024-10-16 23:28:11

屏幕分辨率可能是导致框架错误的原因之一。
就我而言,我更改了屏幕分辨率,但问题并未在该分辨率下产生,当我转回推荐的分辨率时,我就遇到了问题。

Screen Resolution can be one of the reason that cause error in the framework.
In my case i changed my screen resolution and the issue was not produced in that resolution and when ever I shift back to recomended resolution, I got the issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文