-1

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

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

如果它是 ui 线程的一部分,我应该怎么做才能将它放在其他线程上,这样由于 timer_elapse 事件,ui 不应该被冻结。

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

4

2 回答 2

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 线程中执行。您可以将 Dispatcher 从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 );
        }
    }
于 2013-09-18T17:11:40.213 回答
0

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

    Dispatcher.BeginInvoke(new Action(() =>
    {
        // UI code
    }));
于 2013-09-18T16:37:22.080 回答