解决“无法访问已处置对象”的问题。例外 [英] Problems solving "Cannot access disposed object." exception

查看:109
本文介绍了解决“无法访问已处置对象”的问题。例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我当前的项目中,有一个看起来像这样的Form类:

In my current project there is a Form class which looks like this:

public partial class FormMain : Form
{

    System.Timers.Timer timer;
    Point previousLocation;
    double distance;

    public FormMain()
    {
        InitializeComponent();

        distance = 0;
        timer = new System.Timers.Timer(50);
        timer.AutoReset = true;
        timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        timer.Start();
    }

    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (previousLocation != null)
        {
            // some code

            UpdateDistanceLabel(distance);
            UpdateSpeedLabel(v);
        }

        previousLocation = Cursor.Position;
    }

    private void UpdateDistanceLabel(double newDistance)
    {
        if (!lblDistance.IsDisposed && !IsDisposed)
        {
            Invoke(new Action(() => lblDistance.Text = String.Format("Distance: {0} pixels", newDistance)));
        }
    }

    private void UpdateSpeedLabel(double newSpeed)
    {
        if (!lblSpeed.IsDisposed && !IsDisposed)
        {
            Invoke(new Action(() => lblSpeed.Text = String.Format("Speed: {0} pixels per second", newSpeed)));
        }
    }

}

当您可以看到,我正在使用System.Timers.Timer对象。我知道我可以使用System.Windows.Forms.Timer,但是我对标题中仍然显示异常的原因很感兴趣。它在UpdateDistanceLabel方法中的Invoke调用中抛出。令我感到困惑的是,即使我正在检查它是否已处置,它也会显示无法访问已处置的对象:FormMain。所以那不应该发生。我还尝试过在FormClosing事件中放置计时器对象,以及覆盖Dispose(bool)并将其放置在此处,不幸的是,这两者都没有帮助。同样,并非总是会引发异常,据推测只有在程序退出时计时器触发时才会抛出异常。

As you can see, I am using a System.Timers.Timer object. I know I could use System.Windows.Forms.Timer, but I'm fairly interested in the reason why I'm still getting the exception shown in the title. It gets thrown at the Invoke call in the UpdateDistanceLabel method. What confuses me is that it says "Cannot access disposed object: FormMain" even though I am checking whether it is disposed or not. So that shouldn't happen. I have also tried disposing the timer object in the FormClosing event as well as overriding Dispose(bool) and disposing it there, both of which unfortunately didn't help at all. Also, the exception does not always get thrown, supposedly only when the timer happens to fire whilst the program is exiting. It still happens a lot.

我已经看到有很多关于此的线程,但是我已经尝试过那里发布的解决方案,其中大多数涉及检查IsDisposed属性-对我不起作用。所以我想我做错了。

I've seen that there are tons of threads about this, but I've already tried the solutions posted there, most of them involve checking the IsDisposed property - which doesn't work for me. So I guess I am doing something wrong.

所以我的问题是:
即使我正在检查对象是否在上面,为什么上面发布的代码会引发异常

So my question: Why does the code posted above fire an exception even though I am checking whether the objects I am accessing are disposed or not?

推荐答案

有两种解决方法:要么吞下异常,要么诅咒Microsoft未包含 TryInvoke TryBeginInvoke 方法,或者使用锁定来确保不尝试对 Dispose 该对象在使用中,并且在进行 Dispose 时不会尝试使用该对象。我认为吞下异常可能会更好,但是有些人会对此类事情产生内在的反应,使用锁定可以避免发生异常。

There are two workarounds: either swallow the exception and curse Microsoft for not having included a TryInvoke and TryBeginInvoke methods, or else use locking to ensure that no attempt is made to Dispose the object while it's in use, and no attempt is made to use the object while Dispose is in progress. I think swallowing the exception is probably better, but some people have a visceral reaction against such things, and using locking it is possible to avoid having the exception occur in the first place.

这篇关于解决“无法访问已处置对象”的问题。例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆