Форма устранения ошибки Cross Thread с таймером - PullRequest
5 голосов
/ 16 декабря 2011

У меня установлен таймер на 10 секунд в одной из моих окон. А для OnTimedEvent я установил форму, которая будет удалена после истечения времени. Однако, похоже, что ошибка

InvalidOperationException не был обработан кодом пользователя.

Операция с несколькими потоками недопустима: элемент управления «messagesForm» доступен из потока, отличного от потока, в котором он был создан.

Ошибка была на линии

protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

код моего события таймера

    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        this.Dispose();
    }

Кто-нибудь знает, как это исправить? спасибо!

Ответы [ 4 ]

4 голосов
/ 16 декабря 2011

Похоже, вы используете System.Timers.Timer.

Попробуйте вместо этого использовать System.Windows.Forms.Timer и подпишитесь на событие Tick.

Если вам нужно использовать этот таймер, вы можете попробовать изменить свой код так:

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
   this.BeginInvoke((MethodInvoker)delegate { this.Dispose(); });
}
1 голос
/ 12 сентября 2015
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    this.Invoke(new Action(() => this.Dispose()));
}

Это работает как есть

1 голос
/ 16 декабря 2011

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

Базовая вещь, на которую следует обратить внимание: если вы когда-либо пытаетесь изменить объект презентации, созданный в конструкторе, из другого потока, вам нужно проверить, требуется ли вызывать.

void OnTick()
{
    if (InvokeRequired)
        Invoke(new MethodInvoker(OnTick));
    else
    {
        Dispose();
    }
}
1 голос
/ 16 декабря 2011

Или просто:

this.Invoke((Action)(() => { this.Dispose(); }));

Вы можете сделать это в одну строку:

timer1.Tick += (_, __) => { this.Invoke((Action)(() => { this.Dispose(); })); };
...