为什么 C# 中的多线程运行很慢

本文关键字:运行 多线程 为什么 | 更新日期: 2023-09-27 18:34:05

当此代码运行并且所有三个线程都在运行时,标签中随机数的显示会变慢。而当停止一个或两个线程时,处理速度会变快。为什么?

namespace MultiThreadingCheckBox
{
    public partial class Form1 : Form
    {
        Thread t1, t2, t3; 
        public Form1()
        {
            InitializeComponent();
        }
    private void Form1_Load(object sender, EventArgs e)
    {
        t1 = new Thread(new ThreadStart(DoWork1));
        t2 = new Thread(new ThreadStart(DoWork2));
        t3 = new Thread(new ThreadStart(DoWork3));
        t1.Start();
        t2.Start();
        t3.Start();
    }
    private void DoWork1()
    {
        Random p = new Random(); 
        while (true)
        {
            label1.Invoke(new MethodInvoker(delegate { label1.Text = p.Next(1, 1000).ToString(); })); 
        }
    }
    private void DoWork2()
    {
        Random p = new Random();
        while (true)
        {
            label2.Invoke(new MethodInvoker(delegate { label2.Text = p.Next(1, 1000).ToString(); }));
        }
    }
    private void DoWork3()
    {
        Random p = new Random();
        while (true)
        {
            label3.Invoke(new MethodInvoker(delegate { label3.Text = p.Next(1, 1000).ToString(); }));
        }
    }
    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox1.Checked == true)
        {
            t1.Suspend();
            label1.Invoke(new MethodInvoker(delegate { label1.Text = "I am stopped"; }));
        }
        else
            t1.Resume(); 
    }
    private void checkBox2_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox2.Checked == true)
        {
            t2.Suspend();
            label2.Invoke(new MethodInvoker(delegate { label2.Text = "I am stopped"; }));
        }
        else
            t2.Resume(); 
    }
    private void checkBox3_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox3.Checked == true)
        {
            t3.Suspend();
            label3.Invoke(new MethodInvoker(delegate { label3.Text = "I am stopped"; }));
        }
        else
            t3.Resume(); 
    }
}

}

为什么 C# 中的多线程运行很慢

首先,在窗体上显示内容需要 UI 线程才能完成工作。
因此,当您执行 Invoke() 时,您会调用对 UI 线程的同步调用来更改显示。
这意味着线程向 UI 线程发送一条消息,并进入睡眠状态,直到收到完成的信号。

若要避免这种情况,请使用 BeginInvoke ,这将向 UI 线程发送异步消息,并且不会暂停线程。

现在第二个问题是你使用的线程多于你拥有的内核。
因此,由于实际的物理原因,CPU无法真正并行运行它,它没有另一个内核可以做到这一点。
所以这不是真正的并行性,除了线程在调用中进入睡眠状态之外,性能会降低。

首先,因为每次线程等待执行时,您的所有线程进程都有继续循环。

现在第二件事是系统配置。如果您有多核系统,那么每个内核可以执行一个线程,因此如果 4 个内核,那么三个线程并行执行,但如果单核或两个内核,则线程必须等待执行。

第三点是,每次使用 invoke for label 将每个开关上下文更新回 UI 线程时,也会降低和影响应用程序的性能。

顺便说一句,由于Yochai Timmer和dotnetstep已经解释了为什么它执行缓慢,我还想建议使用任务而不是生成自己的线程。任务将为您管理线程池,并且可能比您在不投入太多精力的情况下实际管理的效率更高。

显然,您编写的是一个示例应用程序,因此您可能已经了解任务。在这种情况下,我同意Yochai的观点,您绝对应该使用BeginInvoke来异步访问UI。