Как избежать ObjectDisposedException при закрытии приложения - PullRequest
0 голосов
/ 18 января 2019

У меня проблема с репликацией по всему приложению, но я думаю, что этим можно было бы управлять одинаково.

В моем приложении Winforms есть класс IDisposable (это пользовательский элемент управления, производный от System.Windows.Forms.Label)

В этом классе у меня есть таймер, у которого есть событие тика:

    private void TickTimer(object state)
    {
        Action updateText = () =>
        {
            this.Parent.SuspendLayout();
            this.Text = DateTime.Now.ToString("HH:mm:ss");
            this.Parent.ResumeLayout(false);
        };

        if (this.InvokeRequired)
            this.Invoke(updateText);
        else
            updateText();
    }

С другой стороны, это метод Dispose:

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            Stop();
            _timer.Dispose();
        }
        base.Dispose(disposing);
    }

Проблема заключается в том, что при закрытии приложения возникает исключение в вызове this.Invoke (updateText), сообщающем, что основная форма (где находится элемент управления) была удалена.

Так как это происходит асинхронно, как я могу управлять этим?

Я думал о размещении поля класса с именем, например, _isDisposed и в каждой строке TickTimer, чтобы проверить, было ли оно удалено, но это действительно ужасно.

При поиске здесь в StackOverflow я нашел несколько советов .... ни один не помог. Последняя попытка использовала флаг «обновление».

    private void TickTimer(object state)
    {
        _updating = true;

        Action updateText = () =>
        {
            this.Parent.SuspendLayout();
            this.Text = DateTime.Now.ToString("HH:mm:ss");
            this.Parent.ResumeLayout(false);

            _updating = false;
        };

        if (this.InvokeRequired)
            this.Invoke(updateText);
        else
            updateText();
    }

и в методе утилизации:

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            Stop();
            _timer.Dispose();

            while (_updating) ;
        }
        base.Dispose(disposing);
    }

Но возникает та же ошибка. Кажется, что родительская форма располагается раньше, чем дочерний элемент управления.

Каков наилучший способ сделать это?

Jaime

...