繁体   English   中英

无法访问已处置的对象C#(showdialog处置)

[英]Cannot access a disposed object C# (showdialog dispose)

我是C#的新手,有点喜欢它。 使用Microsoft Visual C#2010

我检查了许多类似的帖子,但这些建议似乎都没有帮助

我收到以下错误:“无法访问已处置的对象”,此处引用了主要形式

private void btn_RunPkgs_Click(object sender, EventArgs e)
        {
            RunPackages rp = new RunPackages();    
            this.Hide();
            rp.ShowDialog();//The error points to this line
            this.Show();
        }

这是安全检查失败时炸毁的代码。

private void securityCheck()
        {
            if (MyGlobals.FormCheck("RUN_JOBS") == 1)
            {
                InitializeComponent();
            }
            else
            {
                //this.BeginInvoke(new MethodInvoker(this.Close));
                //this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
                MessageBox.Show("You do not have permission to access this form!");
                //this.Close();
                this.Dispose();
            }            
        }

编辑看来我将接受Adriano Repetti提出的将安全性放在我称为页面的地方的想法,但是现在我对页面上的任何安全性感到有些紧张。

   private void btn_RunPkgs_Click(object sender, EventArgs e)
        {
            if (MyGlobals.FormCheck("RUN_JOBS") == 1)
            {
                RunPackages rp = new RunPackages();
                this.Hide();
                rp.ShowDialog();
                this.Show();                
            }
            else
            {
                MessageBox.Show("Not for You!");             
            }
        }

        private void btn_ListUpdater_Click(object sender, EventArgs e)
        {
            if (MyGlobals.FormCheck("MDM") == 1)
            {
                ListUpdater lu = new ListUpdater();

                this.Hide();
                lu.ShowDialog();
                this.Show();
            }
            else
            {
                MessageBox.Show("Private!");
            }            
        }

EDIT2提出了以下可能的解决方案,但是由于我是新手,并且不知道可能存在什么问题,因此使用它感到不安。 仅创建用于表单加载的事件处理程序有任何问题吗?

namespace RunPackages
{
    public partial class ListUpdater : Form
    {
        public ListUpdater()
        {            
            InitializeComponent();
            this.Load += new EventHandler(securityCheck);
        }    

        private void securityCheck(object sender, EventArgs e)
        {
            if (MyGlobals.FormCheck("MDM1") == 0)
            {
                MessageBox.Show("Not Allowed!");
                this.Close();
            }    
        }

您不能在表单本身内处理该表单。 ShowDialog()方法尝试在退出时访问DialogResult类的表单。

处理完表单后,几乎无法访问其所有方法(并且大多数属性无效)。

btn_RunPkgs_Click()第一行中,创建一个对象,并将其放置在其构造函数中。 就其本身而言 ,即使是非常坏的习惯,您甚至可以从构造函数中调用Dispose() ,它甚至可能起作用,但是随后您尝试使用此类对象ShowDialog()会生成ObjectDisposedException 请注意,此代码也将导致相同的结果(例外):

RunPackages rp = new RunPackages();
rp.Dispose();

是的,您可以检查IsDisposed但这不会使代码易读,并且问题(IMO)是您正在混合各种东西。 构造函数不应包含此类逻辑。

关键不只是您放置表单的位置。 更好的是甚至不要创建这样的表单(让我假设,因为您调用了InitializeComponent() ,所以securityCheck()在表单构造函数内部被调用),为此,您可以使用工厂静态方法:

public static bool TryShowDialog(Form currentForm)
{
    if (MyGlobals.FormCheck("RUN_JOBS") != 1)
        return false;

    if (currentForm != null)
        currentForm.Hide();

    RunPackages dlg = new RunPackages();
    dlg.ShowDialog();   

    if (currentForm != null)
        currentForm.Show();

    return true;
}

您的调用函数将被简化为:

private void btn_RunPkgs_Click(object sender, EventArgs e)
{
    RunPackages.TryShowDialog(this);
}

请注意,此函数非常适合进行某些重构(例如,提取代码以隐藏/显示现有表单)。 像这样:

public static bool ShowDialog<T>(Form currentForm, string authorizationId)
    where T : Form, new()
{
    if (MyGlobals.FormCheck(authorizationId) != 1)
        return false;

    if (currentForm != null)
        currentForm.Hide();

    T dlg = new T();
    T.ShowDialog();   

    if (currentForm != null)
        currentForm.Show();

    return true;
}

像这样使用(现在代码到处都可以重用):

    SecurityHelpers.ShowDialog<RunPackages>(this, "RUN_JOBS");

请注意,调用代码可以简化(例如, authorizationId可以是RunPackages上的一个属性,也可以从当前活动形式中推断出currentForm )。

EDIT调用Close()更好,如果尚未创建窗口句柄(让我们简化一点:在显示窗口时创建),则在内部调用Dispose() (然后适用)。

我不会尝试破坏导致表单创建的事件链。
副作用很难预测,并且今天有效的方法在将来的版本中无效。

相反,我会尝试另一种方法

    private void securityCheck()
    {
        if (MyGlobals.FormCheck("RUN_JOBS") == 1)
        {
            InitializeComponent();
        }
        else
        {
            Label message = new Label();
            message.Dock = DockStile.Fill;
            message.Text("You do not have permission to access this form!.");
            message.TextAlign = ContentAlignment.MiddleCenter;
            this.Controls.Add(message);
        }      
    }

通过这种方式,我让表单仅显示一个标签,该标签将您的消息覆盖整个表单表面。 用户只能关闭表单(前提是您尚未删除控制箱)

顺便说一句,这样做的好处是可以避免危险的监督,因为它不需要对调用代码进行任何更改,并且最终效果是有效地阻止了表单的使用。

如果您坚持在构造函数阶段关闭表单,则可以从该问题中获得一些建议

我提出了以下建议,有人可以告诉我这是否有问题吗?

namespace RunPackages
{
    public partial class ListUpdater : Form
    {

        public ListUpdater()
        {            
            InitializeComponent();
            this.Load += new EventHandler(securityCheck);
        }    

        private void securityCheck(object sender, EventArgs e)
        {
            if (MyGlobals.FormCheck("MDM1") == 0)
            {
                MessageBox.Show("Not allowed!");
                this.Close();
            }    
        }

等等...

使用标志。 例如,更改代码,如下所示:

    public bool IsDisposed;
    private void securityCheck()
            {
                if (MyGlobals.FormCheck("RUN_JOBS") == 1)
                {
                    InitializeComponent();
                }
                else
                {
                    //this.BeginInvoke(new MethodInvoker(this.Close));
                    //this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
                    MessageBox.Show("You do not have permission to access this form!");
                    //this.Close();
                    this.Dispose();
                    this.IsDisposed = true;
                }      


        }

然后:

private void btn_RunPkgs_Click(object sender, EventArgs e)
        {
            RunPackages rp = new RunPackages();    
            if(rp.IsDisposed)
                return;
            this.Hide();
            rp.ShowDialog();//The error points to this line
            this.Show();
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM