【问题标题】:How can I avoid from getting exception? Cannot access a disposed object when closing my project如何避免异常?关闭我的项目时无法访问已处置的对象
【发布时间】:2016-01-01 15:11:32
【问题描述】:

我正在关闭我的项目,点击右上角的 form1 红色 x 我得到了异常。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenPop;
using OpenPop.Pop3;
using OpenPop.Mime;

namespace Pop3_Emails
{
    public partial class Form1 : Form
    {
        static OpenPop.Pop3.Pop3Client cc = new Pop3Client();
        ProgressBarWithText pbt = new ProgressBarWithText();

        public Form1()
        {
            InitializeComponent();

            pbt.Size = new Size(216, 10);
            pbt.Location = new Point(8, 312);
            groupBox1.Controls.Add(pbt);

            backgroundWorker1.RunWorkerAsync();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            OpenPop.Pop3.Pop3Client PopClient = new OpenPop.Pop3.Pop3Client();
            PopClient.Connect("net.net", 110, false);
            PopClient.Authenticate("meuser", "mepass",
                OpenPop.Pop3.AuthenticationMethod.UsernameAndPassword);
            int messageCount = PopClient.GetMessageCount();
            List<OpenPop.Mime.Message> allMessages = new List<OpenPop.Mime.Message>(messageCount);
            for (int i = messageCount; i > 0; i--)
            {
                allMessages.Add(PopClient.GetMessage(i));
                int nProgress = (messageCount - i) * 100 / messageCount;
                backgroundWorker1.ReportProgress(nProgress, PopClient.GetMessageCount().ToString() + " Number of downloaded messages" + i);
            }
            PopClient.Disconnect();        
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pbt.Value = e.ProgressPercentage;
            pbt.Text = e.ProgressPercentage.ToString() + "%";
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }

        public class ProgressBarWithText : ProgressBar
        {
            const int WmPaint = 15;
            SizeF TextSize;
            PointF TextPos;

            public ProgressBarWithText()
            {
                this.DoubleBuffered = true;
                this.TextChanged += ProgressBarWithText_TextChanged;
                this.SizeChanged += ProgressBarWithText_SizeChanged;
            }

            public override string Text
            {
                get { return base.Text; }
                set { base.Text = value; }
            }

            void RecalcTextPos()
            {
                if (string.IsNullOrEmpty(base.Text))
                    return;

                using (var graphics = Graphics.FromHwnd(this.Handle))
                {
                    TextSize = graphics.MeasureString(base.Text, this.Font);
                    TextPos.X = (this.Width / 2) - (TextSize.Width / 2);
                    TextPos.Y = (this.Height / 2) - (TextSize.Height / 2);
                }
            }

            void ProgressBarWithText_SizeChanged(object sender, EventArgs e)
            {
                RecalcTextPos();
            }

            void ProgressBarWithText_TextChanged(object sender, EventArgs e)
            {
                RecalcTextPos();
            }

            protected override void WndProc(ref System.Windows.Forms.Message m)
            {
                base.WndProc(ref m);

                switch (m.Msg)
                {
                    case WmPaint:
                        using (var graphics = Graphics.FromHwnd(Handle))
                            graphics.DrawString(base.Text, base.Font, Brushes.Black, TextPos.X, TextPos.Y);

                        break;
                }
            }

            protected override CreateParams CreateParams
            {
                get
                {
                    CreateParams result = base.CreateParams;
                    result.ExStyle |= 0x02000000; // WS_EX_COMPOSITED 
                    return result;
                }
            }
        }
    }
}

例外是在ProgressBarWithText类就行了:

var graphics = Graphics.FromHwnd(this.Handle)

无法访问已处置的对象

所以我现在添加了 form1 结束事件。 我应该在活动中放什么?停止和处置什么?

【问题讨论】:

  • 您的关闭事件处理程序在哪里?难道你不能在你的类中添加一个私有标志,然后如果设置了该标志就不能读取 WmPaint 吗?
  • Tim 如果标志是私有的,那么我什么时候将其设置为 true ?无法从 form1 关闭事件处理程序访问它。如果它是真正的油漆,但我在哪里将它设置为 false ?
  • 当用户试图关闭窗口时,backgroundWorker 应该怎么做?
  • 取消操作。也许在 form1 关闭事件中添加一个消息框来询问用户是否要取消它。但是在后台worker取消。

标签: c# .net winforms


【解决方案1】:

编码比解释更容易。另外,还没有测试过,但它在我的脑海中有效:

private bool closingForm = false;

// Note, this is "Closing" event handler, not "Close"
Form1_Closing(object sender, CancelEventArgs e)
{
    if (!closingForm && MessageBox.Show("You sure?", "Form1", MessageBoxButtons.YesNo) == DialogResult.No)
    {
        e.Cancel = true;
    }
    else if (backgroundWorker1.IsBusy)
    {
        e.Cancel = true;
        closingForm = true;
        if (!backgroundWorker1.CancellationPending)
            backgroundWorker1.CancelAsync();
    }
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (closingForm)
        this.Close();
}

在backgroundWorker1_DoWork 中,如果backgroundWorker1.CancellationPending 是true,则必须在循环中检查,然后将e.Cancel 设置为true,并且只需在方法中设置return。

无论如何,很少解释。用户发起关闭,因此表单发起后台线程的取消。但实际完成要晚些,然后我们才会关闭表单,注意不要第二次干扰Closing 和Close 事件。

【讨论】:

    【解决方案2】:

    您可以在使用之前检查对象是否已经被释放

    void RecalcTextPos()
    {
        if (this.IsDisposed == true)
            return;
        if (string.IsNullOrEmpty(base.Text))
            return;
    
        using (var graphics = Graphics.FromHwnd(this.Handle))
        {
            TextSize = graphics.MeasureString(base.Text, this.Font);
            TextPos.X = (this.Width / 2) - (TextSize.Width / 2);
            TextPos.Y = (this.Height / 2) - (TextSize.Height / 2);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 2011-10-23
      • 2011-03-25
      相关资源
      最近更新 更多