为什么在单击ToolStrip按钮两次时抛出NullReferenceException - openFileDialog.showDialog()?

时间:2011-01-02 02:19:40

标签: c# .net nullreferenceexception openfiledialog toolstripbutton

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

ToolStripButton

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

有趣的是,当我双击private void toolStripButton1_Click(object sender, EventArgs e) { openFileDialog1.ShowDialog(); } 时(第二次点击必须非常快,在对话框打开之前),然后取消两个对话框(或选择一个文件,这并不重要)然后单击主窗体的客户区域,ToolStripButton崩溃应用程序(帖子末尾附带的错误详细信息)。 请注意NullReferenceException事件是在Click不是时实施的。

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

我在 Windows 7专业版(来自MSDNAA)上使用带有.NET3.5的VS2008以及最新更新。我没有在VS中更改很多选项(只有fontsize,工作区文件夹和行编号)。

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

我能想到的一个解决方案是在调用ToolStripButton之前禁用按钮然后再启用按钮(但这并不好)。还有其他想法吗?

现在承诺的错误详情:

  

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 reason,Int32 pvLoopData)
            在System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason,ApplicationContext context)
            在System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason,ApplicationContext context)
            在System.Windows.Forms.Application.Run(Form mainForm)
            在WindowsFormsApplication1.Program.Main()w C:\ Users \ Marchewek \ Desktop \ Workspaces \ VisualStudio \ WindowsFormsApplication1 \ Program.cs:第20行
            在System.AppDomain._nExecuteAssembly(Assembly assembly,String [] args)
            在System.AppDomain.ExecuteAssembly(String assemblyFile,Evidence assemblySecurity,String [] args)
            在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
            在System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
            在System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback回调,对象状态)
            在System.Threading.ThreadHelper.ThreadStart()
   InnerException:

3 个答案:

答案 0 :(得分:2)

我能够在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; 

    }

下次升级框架时,可以尝试将其删除。

尼尔

答案 1 :(得分:0)

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

在框架有机会为OpenFileDialog提供独占的UI焦点之前,快速双击您再次调用ShowDialog的按钮。这使您的应用程序处于无效状态。

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

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

答案 2 :(得分:0)

屏幕分辨率可能是导致框架中出错的原因之一。 在我的情况下,我改变了我的屏幕分辨率,并没有在该分辨率中产生问题,当我转回到推荐的分辨率时,我遇到了问题。