主线程和子线程的区别

每个线程都有一个唯一标示符,来区分线程中的主次关系的说法。
线程唯一标示符:Thread.CurrentThread.ManagedThreadID;

  • UI界面和Main函数均为主线程。
  • Thread包含的“方法体”或者“委托”均为子线程。
  • 委托可以包含多个方法体,利用this.Invoke去执行。
  • 也可以定义多种方法体,放在Thread里面去执行。则此方法体均为子线程。注意如果要修改UI界面的显示。则需要使用this.Invoke,否则会报异常。
  • Main函数为主线程,id标示符与UI界面主线程相等

不多说了。看下面的测试代码注释吧。

public delegate void dele();
    public partial class Form1 : Form
    {
        int idA;
        public dele getlab;
        public Form1()
        {
            InitializeComponent();
            idA  = Thread.CurrentThread.ManagedThreadId;//UI界面主线程
            /*
             * Main函数为主线程,id标示符与UI界面主线程相同。
             */
        }

        Thread thread;
        private void getbtu_Click(object sender, EventArgs e)//UI控件属于主线程
        {
            int idB = Thread.CurrentThread.ManagedThreadId;
            getlab = new dele(getLabel);//委托添加方法
            getlab += new dele(gg);//委托在叠加一个方法
            getlab += new dele(kk);//委托在叠加一个方法
            //
            thread = new Thread(new ThreadStart(delegate
            {
                int idC = Thread.CurrentThread.ManagedThreadId;//Thread开辟一个子线程
                //gg();//方法直接在thread里面调用均为子线程
                //kk();//方法直接在thread里面调用均为子线程
                getlab();//委托直接在thread里面调用,委托里面的方法为子线程

                //以上因为都包含在thread里面
                MessageBox.Show("显示完成");

                //this.Invoke(getlab);
                /*错误提示:主线程调用主线程当然会假死*/
            }));
            thread.IsBackground = true;
            thread.Start();
        }
        public void kk()//委托中的方法  委托方法三
        {
            int idR = Thread.CurrentThread.ManagedThreadId;
            this.Invoke((dele)(() =>//修改UI界面值则需要加this.Invoke
            {                 
                    label2.Text = "ABC";
            }));
        }
        public void gg()//委托中的方法  委托方法二
        {
            int idP = Thread.CurrentThread.ManagedThreadId;
            this.Invoke((dele)(() =>//修改UI界面值则需要加this.Invoke
            {
                    label3.Text = "QWE";
            }));
        }
        public void getLabel()//委托中的方法 委托方法一
        {       
            int idD = Thread.CurrentThread.ManagedThreadId;//子线程

            for (int i = 0; i <= 1000; i++)
            {
                Thread.Sleep(10);
                //this.Invoke为主线程,执行子线程的内容
                this.Invoke((dele)(() =>
                {
                    getlabel.Text = i.ToString();
                    int idE = Thread.CurrentThread.ManagedThreadId;//主线程
                    Console.WriteLine("线程idE:" + idE);
                }));
                Console.WriteLine(i);
            }
            MessageBox.Show("显示完成");
        }

        private void sleepbtu_Click(object sender, EventArgs e)//UI控件属于主线程
        {
            int idF = Thread.CurrentThread.ManagedThreadId;
            try
            {
                if (thread.ThreadState != ThreadState.Suspended)
                {
                    thread.Suspend();
                }
            }
            catch (Exception r)
            {
                MessageBox.Show(r.Message);
            }
        }

        private void setbtu_Click(object sender, EventArgs e)//UI控件属于主线程
        {
            int idG = Thread.CurrentThread.ManagedThreadId;
            try
            {
                if (thread.ThreadState != ThreadState.Running)
                {
                    thread.Resume();
                }
            }
            catch (Exception r)
            {
                MessageBox.Show(r.Message);
            }
        }

        public void getlabel_Click(object sender, EventArgs e)
        {

        }
    }

总结:

  1. 什么是子线程?
    包含在 Thread thread = new Thread(new ThreadStart(delegate{ }));里面均视为子线程。(个人理解)
  2. 什么是主线程?
    UI界面和Main函数均为主线程,除了“不包含在Thread里面的程序”均可 视为主线程。(个人理解)
### QT 中区分判断主线程子线程的方法 在 Qt 应用程序中,可以通过 `QThread::currentThreadId()` 函数获取当前线程的 ID 来区分主线程子线程。此外,`qApp->thread()` 可用于返回应用程序对象所在的线程,通常这是主线程。 对于更直观的方式,在代码逻辑层面也可以利用宏定义或特定条件语句来进行判定: #### 使用 QThread::currentThread() 可以直接调用静态成员函数 `QThread::currentThread()` 获取指向当前正在运行的线程的对象指针,并将其与已知的主线程实例对比。如果两者相等,则说明当前处于主线程;反之则为其他线程。 ```cpp if (QThread::currentThread() == qApp->thread()) { qDebug() << "This is the main thread."; } else { qDebug() << "This is a sub-thread."; } ``` #### 利用 QObject 的线程属性 由于所有的 GUI 组件都必须位于主线程内工作,因此可以借助这一点来做进一步验证。任何继承自 `QObject` 类的对象都可以访问其所属线程的信息。比如下面的例子展示了如何在一个类方法内部检查自己是否处在主线程之中[^1]。 ```cpp void MyClass::someMethod() { if (this->thread() != QCoreApplication::instance()->thread()) qDebug("Not running on the main thread"); else qDebug("Running on the main thread"); } ``` 以上两种方式能够有效地帮助开发者识别并处理不同类型的线程环境下的任务分配问题。值得注意的是,在实际开发过程中应当遵循最佳实践原则——即尽可能减少跨线程间的直接交互频率,更多地依赖于信号槽机制完成必要的通信需求[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值