SaveFileDialog.ShowDialog() 似乎没有理由抛出 System.AccessViolationException

SaveFileDialog.ShowDialog() throws an System.AccessViolationException for seemingly no reason

我正在尝试在我的 windows 表单项目中使用保存文件对话框。尝试保存文件时,我使用 showDialog() 方法并抛出 System.AccessViolationError。保存文件对话框的初始目录未设置,所以我不明白为什么会出现访问冲突。这是我为使用保存文件对话框编写的代码:

var imageSaver = new SaveFileDialog();
imageSaver.Filter = fileType + " File|*." + fileType;
imageSaver.Title = "Save Image";
if (imageSaver.ShowDialog() == DialogResult.OK)
{
    b.Save(imageSaver.FileName, imgFormat);
    Close();
}

此代码块用在单击按钮时的事件中,但是,经过一些测试后,我发现相同的代码在窗体的构造函数和加载事件中使用时有效的形式。

这里是完整的 class:

using System.Drawing.Imaging;

namespace Pixart
{
    public partial class ImageGenerator : Form
    {
        int width;
        int height;
        Cell[,] cells;
        ImageFormat imgFormat;
        string fileType;

        bool useMultiplier;

        public ImageGenerator(string fileType, ImageFormat imgFormat, Cell[,] cells, int width, int height)
        {
            InitializeComponent();
            this.width = width;
            this.height = height;
            this.cells = cells;
            this.imgFormat = imgFormat;
            this.fileType = fileType;

            titleLabel.Text = "Export " + fileType.ToUpper();

            widthNumber.Minimum = width;
            widthNumber.Increment = width;
            widthNumber.Maximum = (4000 / width) * width;
            heightNumber.Minimum = height;
            heightNumber.Increment = height;
            heightNumber.Maximum = (4000 / height) * height;

            if (heightNumber.Maximum / height < widthNumber.Maximum / width)
                multiplierNumber.Maximum = heightNumber.Maximum / height;
            else
                multiplierNumber.Maximum = widthNumber.Maximum / width;

            widthLabel.ForeColor = SystemColors.ControlDarkDark;
            heightLabel.ForeColor = SystemColors.ControlDarkDark;
            sizeLabel.ForeColor = SystemColors.ControlDarkDark;
            multiplierLabel.ForeColor = SystemColors.ControlText;
            useMultiplier = true;

            //The code works here for some reason
            //var imageSaver = new SaveFileDialog();
            //imageSaver.Filter = fileType + " File|*." + fileType;
            //imageSaver.Title = "Save Image";
            //if (imageSaver.ShowDialog() == DialogResult.OK)
            //{
                
            //}
        }

        private void ImageGenerator_Load(object sender, EventArgs e)
        {
            //The code also works here
            //var imageSaver = new SaveFileDialog();
            //imageSaver.Filter = fileType + " File|*." + fileType;
            //imageSaver.Title = "Save Image";
            //if (imageSaver.ShowDialog() == DialogResult.OK)
            //{

            //}
        }

        private void multiplierNumber_ValueChanged(object sender, EventArgs e)
        {
            widthLabel.ForeColor = SystemColors.ControlDarkDark;
            heightLabel.ForeColor = SystemColors.ControlDarkDark;
            sizeLabel.ForeColor = SystemColors.ControlDarkDark;
            multiplierLabel.ForeColor = SystemColors.ControlText;
            useMultiplier = true;
        }

        private void widthNumber_ValueChanged(object sender, EventArgs e)
        {
            widthLabel.ForeColor = SystemColors.ControlText;
            heightLabel.ForeColor = SystemColors.ControlText;
            multiplierLabel.ForeColor = SystemColors.ControlDarkDark;
            sizeLabel.ForeColor = SystemColors.ControlText;
            useMultiplier = false;

            widthNumber.Value = (widthNumber.Value / width) * width;
        }

        private void heightNumber_ValueChanged(object sender, EventArgs e)
        {
            widthLabel.ForeColor = SystemColors.ControlText;
            heightLabel.ForeColor = SystemColors.ControlText;
            multiplierLabel.ForeColor = SystemColors.ControlDarkDark;
            sizeLabel.ForeColor = SystemColors.ControlText;
            useMultiplier = false;

            heightNumber.Value = (Convert.ToInt32(heightNumber.Value) / height) * height;
        }

        private void saveButton_Click(object sender, EventArgs e)
        {
            int imageWidth = width * Convert.ToInt32(multiplierNumber.Value);
            int imageHeight = height * Convert.ToInt32(multiplierNumber.Value);
            if (!useMultiplier)
            {
                imageWidth = Convert.ToInt32(widthNumber.Value);
                imageHeight = Convert.ToInt32(heightNumber.Value);
            }

            using (Bitmap b = new Bitmap(imageWidth, imageHeight))
            {
                for (int r = 0; r < height; r++)
                {
                    for (int c = 0; c < width; c++)
                    {
                        for (int y = 0; y < imageHeight / height; y++)
                        {
                            for (int x = 0; x < imageWidth / width; x++)
                            {
                                b.SetPixel((c * (imageWidth / width)) + x, (r * (imageHeight / height)) + y, cells[c, r].Colour);
                            }
                        }
                    }
                }

                var imageSaver = new SaveFileDialog();
                imageSaver.Filter = fileType + " File|*." + fileType;
                imageSaver.Title = "Save Image";
                //line after this throws an error
                if (imageSaver.ShowDialog() == DialogResult.OK)
                {
                    b.Save(imageSaver.FileName, imgFormat);
                    Close();
                }
            }
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void ImageGenerator_Deactivate(object sender, EventArgs e)
        {
            Close();
        }
    }
}

您的代码中出现错误消息 System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory 是因为 SaveFileDialog 打开时会发生表单 Deactivate 事件。

问题是由以下代码引起的:

private void ImageGenerator_Deactivate(object sender, EventArgs e)
{
    Close();
}

解决方案:删除Close()(或注释掉)

private void ImageGenerator_Deactivate(object sender, EventArgs e)
{

}