2013-09-18 2 views
-1

Я использую класс System.timer.timer для опроса некоторого аппаратного устройства через COM-порт (последовательная связь) через каждые 20 секунд, я запускаю timer.start() из моего UI класса и timer_elapse() событие также находится в классе пользовательского интерфейса.system.timer.timer не является нитью или не

Мой вопрос timer_elapse запускается на другой поток, чем нить ui или в том же потоке? моя озабоченность не связана с тем, как я могу обновить некоторые вещи от timer_elapse до пользовательского интерфейса, но это что-то связано с производительностью. (.net 3.5 Framework)

Если его часть нити ui, чем то, что я должен сделать, чтобы взять ее на другой поток, так что из-за события timer_elapse ui не должно замерзать.

Я новичок на C#, поэтому любая обратная связь будет очень заметна.

+0

возможно дубликат [? Do C# Таймеры истечь в отдельном потоке] (http://stackoverflow.com/ вопросы/1435876/do-c-sharp-timers-elapse-on-a-an-thread) –

ответ

2

При запуске объекта Timer через Start() функцию, она создает новый поток и ждет, пока истекшее время, а затем, когда время истекло, то Подписанные функции или лямбда или делегат вызывается из таймера созданный поток. Итак, в случае вашего примера timer_elapse работает в совершенно другом потоке. Смотрите пример ниже из образца WPF MainClass:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     System.Threading.Thread.CurrentThread.Name = "UI THREAD"; 
     System.Timers.Timer t = new System.Timers.Timer(500); 
     System.Threading.Thread td = new System.Threading.Thread(
      (obj) => 
      { 
       Console.WriteLine("Thread"); 
       t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed); 
       t.Start(); 
       while (true) 
       { 
        System.Threading.Thread.Sleep(1000); 
        Console.WriteLine("From Lambda: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name); 
       } 
      } 
      ); 
     td.Name = "K's Thread"; 
     td.Start(null); 
    } 

    void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     Console.WriteLine("t_Elapsed: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name); 
    } 
} 

и обратите внимание на вывод в консоли отладки, что имя Thread функции таймера не является таким же именем, как UI Thread.

Таким образом, вам не придется беспокоиться о том, чтобы повесить ваш поток пользовательского интерфейса. Но если вы попытаетесь изменить некоторые элементы управления, это может вызвать исключение (не всегда). Поэтому для выполнения любой связанной с UI работы лучше всего делать это в потоке пользовательского интерфейса. Вы можете сделать это Получение диспетчером в потоке пользовательского интерфейса от Application.Current.Dispatcher

Пример ниже:

public partial class MainWindow : Window 
    { 
     delegate void TestDelegate(); 
     public MainWindow() 
     { 
      InitializeComponent(); 

      System.Threading.Thread.CurrentThread.Name = "UI THREAD"; 
      System.Timers.Timer t = new System.Timers.Timer(500); 
      System.Threading.Thread td = new System.Threading.Thread(
       (obj) => 
       { 
        Console.WriteLine("Thread"); 
        t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed); 
        t.Start(); 
        while (true) 
        { 
         System.Threading.Thread.Sleep(1000); 
         Console.WriteLine("From Lambda: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name); 
        } 
       } 
       ); 
      td.Name = "K's Thread"; 
      td.Start(null); 
     } 

     void DoInUIThread() 
     { 
      Console.WriteLine("DoInUIThread: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name); 
     } 

     void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
     { 
      Console.WriteLine("t_Elapsed: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name); 
      TestDelegate td = new TestDelegate(DoInUIThread); 
      Application.Current.Dispatcher.BeginInvoke(td); 
     } 
    } 
+0

Предполагается, что приложение использует WPF или WinRT, также см. Комментарий Брайана Гидеона –

+0

Не могу заставить это работать. Downvote. –

0

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

Dispatcher.BeginInvoke(new Action(() => 
    { 
     // UI code 
    })); 
+0

будет здорово, если вы сможете предоставить мне какие-то ссылки или что-то еще, что, несомненно, поможет понять концепцию полностью. –

+1

@ HarshalSam Почему? Это простой вопрос «да/нет». Код таймера мог быть написан для перехода в контекст пользовательского интерфейса или нет; этот конкретный таймер не делает. Вот и все. Если вы хотите использовать таймер, который будет маршировать в потоке пользовательского интерфейса, в нем много чего, в зависимости от вашего конкретного интерфейса. – Servy

+0

http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.begininvoke.aspx – DaveDev

Смежные вопросы