为什么这段代码会发送跨线程操作异常?

Why is this code sending a cross thread operation exception?

我一直在尝试实现一个 CPU 监视器,它每两秒更新一次并将其显示在 WinForms 中名为“cpu_usage”的标签上。不幸的是,我的代码似乎无法正常工作,并在运行时发出此错误:

 System.InvalidOperationException: 'Cross-thread operation not valid: Control 'cpu_usage' accessed from a thread other than the thread it was created on.'

到目前为止我已经做了一些调试,发现每当我尝试在“cpu-usage”标签上显示百分比时都会出现错误,但我仍然无法弄清楚如何解决这个问题。 CPU监控代码如下:

    public my_form()
    {
        InitializeComponent();

        // Loads the CPU monitor
        cpuCounter = new PerformanceCounter();
        cpuCounter.CategoryName = "Processor";
        cpuCounter.CounterName = "% Processor Time";
        cpuCounter.InstanceName = "_Total";
        InitTimer();
    }

    // Timer for the CPU percentage check routine
    public void InitTimer()
    {
        cpu_timer = new Timer();
        cpu_timer.Elapsed += new ElapsedEventHandler(cpu_timer_Tick);
        cpu_timer.Interval = 2000;
        cpu_timer.Start();
    }

    // Initates the checking routine
    private void cpu_timer_Tick(object sender, EventArgs e)
    {
        cpu_usage.Text = getCurrentCpuUsage(); // This line causes the exception error.
    }

    // Method to find the CPU resources
    public string getCurrentCpuUsage()
    {
        string value1 = (int)cpuCounter.NextValue() + "%";
        Thread.Sleep(500);
        string value2 = (int)cpuCounter.NextValue() + "%";
        return value2.ToString();
    }

我设法通过使用 System.Windows.Forms 作为计时器来修复此错误,而不是使用 System.Timers.Timer 命名空间。此外,我更改了我的代码以使用 await 和 async,以确保线程 运行 用户界面在更新期间不会被冻结。新代码如下:

    // Timer for the CPU percentage check routine
    public void InitTimer()
    {
        cpu_timer.Tick += new EventHandler(cpu_timer_Tick);
        cpu_timer.Interval = 2000; // in miliseconds
        cpu_timer.Start();
    }

    // Initates the checking routine
    private async void cpu_timer_Tick(object sender, EventArgs e)
    {
        Task<string> cpu_task = new Task<string>(getCurrentCpuUsage);
        cpu_task.Start();
        cpu_usage.Text = await cpu_task;
    }

就像其他人所说的那样,我相信你想在 UI 线程上执行文本设置......可以尝试这样的事情:

    // Initates the checking routine
    private void cpu_timer_Tick(object sender, EventArgs e)
    {
        cpu_usage.Invoke((MethodInvoker)delegate {
            // Running on the UI thread
            cpu_usage.Text = getCurrentCpuUsage();
        });
    }