system.timer.timer不是ui线程或不是

时间:2013-09-18 16:35:39

标签: c# multithreading user-interface timer

我使用System.timer.timer类在每20秒后通过com端口(串行通信)轮询一些硬件设备,我从我的UI类启动timer.start()并且timer_elapse()事件也在UI类。

我的问题是在ui线程或同一线程的其他线程上运行timer_elapse?我关注的不是如何将一些东西从timer_elapse更新到UI,而是它与性能相关的东西。 (.net 3.5框架)

如果它的部分ui线程比我应该做的那样把它带到其他线程上,这样因为timer_elapse事件ui不应该被冻结。

我是C#的新手,所以任何反馈都会非常明显。

2 个答案:

答案 0 :(得分:2)

当你通过Start()函数启动一个Timer对象时,它创建一个新线程并等待经过的时间,然后当时间结束时,然后从定时器创建的线程调用预订函数或lambda或委托。因此,在您的示例中,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);
    }
}

并注意调试控制台中Timer函数的Thread名称与UI Thread名称不同的输出。

所以你不必担心挂起你的UI线程。但是如果你试图改变一些控件,它可能会抛出异常(并不总是)。因此,要执行任何与UI相关的工作,最好在UI线程中执行此操作。您可以从Application.Current.Dispatcher

获取Dispatcher到UI线程

示例如下:

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 );
        }
    }

答案 1 :(得分:0)

timer_elapse在与UI不同的线程上运行。如果要在timer_elapse中引用UI组件,则需要使用Dispatcher,例如

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