.NET WinForms错误(SaveFileDialog)?

4
以下示例仅展示了在ToolStripButton单击事件上显示并保存SaveFileDialog。如果我预制SaveFileDialog,然后双击ToolStripButton,应用程序将堆栈溢出。在Winforms中似乎是个bug。对于能否得到修复或甚至MS的响应不抱有太多希望(即使几年前我报告了一个bug,他们也只回答"winforms没有更多的错误修复"),所以我只想听听一些关于这是否是bug或者我的操作有误的意见。
using System;
using System.Windows.Forms;

namespace ToolStripDoubleClickSaveDialog
{
   public partial class Form1 : Form
   {
      SaveFileDialog sfd = new SaveFileDialog();

      public Form1()
      {
         InitializeComponent();
      }

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

      private void InitializeComponent()
      {
         this.toolStrip1 = new System.Windows.Forms.ToolStrip();
         this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
         this.toolStrip1.SuspendLayout();
         this.SuspendLayout();
         // 
         // toolStrip1
         // 
         this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.toolStripButton1});
         this.toolStrip1.Location = new System.Drawing.Point(0, 0);
         this.toolStrip1.Name = "toolStrip1";
         this.toolStrip1.Size = new System.Drawing.Size(284, 25);
         this.toolStrip1.TabIndex = 0;
         this.toolStrip1.Text = "toolStrip1";
         // 
         // toolStripButton1
         // 
         this.toolStripButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
         this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
         this.toolStripButton1.Name = "toolStripButton1";
         this.toolStripButton1.Size = new System.Drawing.Size(23, 22);
         this.toolStripButton1.Text = "double click me";
         this.toolStripButton1.Click += new System.EventHandler(this.toolStripButton1_Click);
         // 
         // Form1
         // 
         this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
         this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
         this.ClientSize = new System.Drawing.Size(284, 262);
         this.Controls.Add(this.toolStrip1);
         this.Name = "Form1";
         this.Text = "Form1";
         this.toolStrip1.ResumeLayout(false);
         this.toolStrip1.PerformLayout();
         this.ResumeLayout(false);
         this.PerformLayout();

      }

      private System.Windows.Forms.ToolStrip toolStrip1;
      private System.Windows.Forms.ToolStripButton toolStripButton1;
   }
}

您可能会对这个答案感兴趣。 - Scott Solmer
1
嗯...我知道什么是stackoverflow异常...那不是问题的点。 - user109078
2
能否提供能够重现问题的代码?您所发布的代码看起来很好。 - gunr2171
当我的事件处理程序意外调用事件本身时,通常会发生这种情况。结果会形成一个循环触发事件。有时我会有一个按钮,我首先实现逻辑,然后是调用该按钮的工具栏项,但我会无意中调用工具栏事件...因此会发生循环。 - TheNorthWes
@gunr2171 对我来说并没有100%发生,但如果双击后打开对话框之前有任何延迟,它会两次到达.ShowDialog()并触发错误。我猜电脑越慢,重现就越容易。 - corylulu
显示剩余3条评论
1个回答

3
好的,问题出在控件被双击时,因为它设置为单击打开对话框,而两个点击事件都试图同时打开对话框。我猜测,在对话框加载时,应用程序会进入一个短暂的空闲状态,然后对话框打开,这足以允许其他事件也被调用,当它调用 ShowDialog() 两次时就会导致错误。
为了防止这种情况发生,您可以获取窗口的 System.Runtime.Remoting.Lifetime.Lease 并在显示之前再次检查它是否处于活动状态。
using System.Runtime.Remoting.Lifetime;
//.....
private SaveFileDialog sfd;
private ILease sfdLease;

public Form1()
{
    InitializeComponent();
    sfd = new SaveFileDialog();
    sfdLease= (ILease)sfd.InitializeLifetimeService();
}
private void toolStripButton1_Click(object sender, EventArgs e)
{
    if(sfdLease.CurrentState != LeaseState.Active)
        sfd.ShowDialog(this);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接