Событие My Timer падает, потому что события вызываются в другом потоке - PullRequest
2 голосов
/ 29 августа 2009

Я получаю сообщение об ошибке «Операция между потоками недопустима: доступ к элементу управления label1 выполняется из потока, отличного от потока, в котором он был создан». когда я запускаю этот код:

using System;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Timers;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        System.Timers.Timer T = new System.Timers.Timer();
        public Form1()
        {
            InitializeComponent();
            T.Elapsed += new ElapsedEventHandler(T_Elapsed);
            T.Start();
        }

        void T_Elapsed(object sender, ElapsedEventArgs e)
        {
            label1.Text = "This will not work";
        }
    }
}

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

Ответы [ 8 ]

3 голосов
/ 29 августа 2009

Хотя ответ «Принято» является технически правильным (то есть это решит проблему), он не отвечает на вопрос.

ОТВЕТ должен использовать

void T_Elapsed(object sender, ElapsedEventArgs e)
{
    this.BeginInvoke(new MethodInvoker(delegate(){
        label1.Text = "This will work";
    }));
}

http://jaysonknight.com/blog/archive/2007/02/14/using-anonymous-methods-for-control-invoke-control-begininvoke.aspx

3 голосов
/ 29 августа 2009

У нас есть 3 класса Timer в NET (Timers.Timer, Threading.Timer и Windows.Forms.Timer), но только в Windows.Forms один имеет событие Tick.

При обычном использовании (то есть при перетаскивании на форму во время разработки или создании в каком-либо коде формы) событие запускается в главном потоке, и ваша проблема не должна возникать.

Поэтому наиболее вероятно, что вы создадите объект Timer в другом потоке, вам, вероятно, следует отредактировать свой вопрос, чтобы показать нам, как / где вы его создаете, и сообщить нам, если он намеренно находится в другом потоке.

2 голосов
/ 29 августа 2009

Возможно, вы используете неправильный таймер. Попробуйте таймер WinForms, он работает в потоке GUI, поэтому вам не нужно делать Invoke

1 голос
/ 25 августа 2011

Да, события выполняются в том же потоке, который их вызвал. Просто так получается, что System.Timers.Timer использует поток ThreadPool по умолчанию при вызове события Elapsed. Используйте свойство SynchronizingObject, чтобы обработчик событий Elapsed выполнялся в потоке, в котором размещен целевой объект.

public partial class Form1 : Form
{
  System.Timers.Timer T = new System.Timers.Timer();

  public Form1()
  {
    InitializeComponent();
    T.Elapsed += new ElapsedEventHandler(T_Elapsed);
    T.SynchronizingObject = this;
    T.Start();
  }

  void T_Elapsed(object sender, ElapsedEventArgs e)
  {
    label1.Text = "This will not work";
  }
}
1 голос
/ 29 августа 2009

Я предполагаю, что вы говорите о приложении WinForms.

При попытке обновить элемент Form (который находится в потоке пользовательского интерфейса) из другого потока, вам необходимо использовать Control.Invoke или Control.BeginInvoke . Вы передаете делегата методу, который хотите вызвать (или передаете анонимный метод), и затем этот делегат вызывается в потоке пользовательского интерфейса, а не в вызывающем потоке.

1 голос
/ 29 августа 2009

Вы не забыли использовать InvokeRequired ? Это позволит вам обновить элемент пользовательского интерфейса в потоке пользовательского интерфейса из потока таймера.

0 голосов
/ 29 августа 2009

Я не разработчик winform. Но я слышал кое-что о классе Timer, который вы используете. Я думаю, что вы можете установить эти свойства и проверить.

T.Interval = 5000; //in Mili Seconds
T.Enabled = true;
0 голосов
/ 29 августа 2009

Если вы делаете это асинхронно (звучит так, как вы), убедитесь, что вы перехватываете исключения в обработчике событий или обратном вызове. Если фоновый поток генерирует исключение, это приведет к сбою приложения. Это самая распространенная причина такого поведения, которую я видел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...