zoukankan      html  css  js  c++  java
  • C# 线程

    进程:就好比你运行一个程序,打开一个记事本等。一个进程至少有一个线程,同一个进程中可以有多个线程“并发”执行。其实多线程并发执行,就是多个线程之间不停地切换,只不过切换的速率过快。

    线程肯定要执行一段代码。所以要产生一个线程,必须先为这个线程写一个方法,这个方法的中的代码就是为线程运行所要执行的代码。线程启动时,需要委托来调用这个方法。所调用的方法都是没有返回值的。

    为什么要使用线程?

    1,让计算机能“同时间”做更多的事情,提高效率。、

    2,后台运行程序时,提高程序的运行效率,也不会使界面出现无响应状态

    3,减少计算机cpu所处的空闲状态

    产生线程的步骤:

    1,编写产生线程所要执行的方法;

    2,引用System.Threading命名空间

    3,实例化Thread类,并传入一个指向线程所要运行方法的委托、

    4,调用线程的start方法,开启线程

    单线程与多线程

     private void button1_Click(object sender, EventArgs e)
            {
                          for (long i = 0; i < 999999999999; i++)
                { }
                MessageBox.Show("Hello,Over");
            }

    若只有这个UI单线程,那么当点击界面的Button按钮时,在执行代码期间,我们将拖不动UI界面。我们只有在另外建一个线程,用那个线程调用这个循环才能解决问题。

    前台线程和后台线程区别:

            public void demo()
            {

                for (long i = 0; i < 999999999999; i++)
                { }
                MessageBox.Show("Hello,Over");

            }

            private void button1_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(demo);
                th.Start();
            }

    这是一个新建的线程,当正在执行代码时,我们关闭窗体,但程序还未结束,等程序运行完这个循环后,将会弹出信息框。

    一般线程都默认为前台线程,只有设置 th.IsBackground = true;将它设置为后台线程。

    前台线程:只有所有前台线程都关闭了,才能使程序结束

    后台线程;只有所有前台线程都结束了,后台线程会自动结束

    线程重入问题

    微软有一个检查线程重入问题,也就是我新建的一个线程不能访问界面UI线程的文本框内容。

     public void demo()
            {

                for (long i = 0; i < 9999; i++)
                {
                    int a = int.Parse(textBox1.Text);
                    a++;
                    textBox1.Text = a.ToString();
                } 

            }

      private void button1_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(demo);
                th.Start();
            }

    线程间操作无效: 从不是创建控件“textBox1”的线程访问它。

    也就是,我自定义的线程th无法操作UI线程的控件。若解决这个问题需要, TextBox.CheckForIllegalCrossThreadCalls = false;关闭它的重入检查。

    若两个线程都执行循环,但执行的结果并不是两者之间的累加,如例题;

      public void demo()
            {
                for (long i = 0; i < 1000; i++)
                {
                    int a = int.Parse(textBox1.Text);
                    a++;
                    textBox1.Text = a.ToString();
                    Console.WriteLine(Thread.CurrentThread.Name + a);
                }
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(demo);
                th.Name = "线程1";
                th.Start();
                Thread th1 = new Thread(demo);
                th1.Name = "线程2";
                th1.Start();
            }

    执行的结果并不是2000,而是1078,这并不代表着执行的次数,如图线程1和线程2总是互相切换执行,他们各自的线程次数是满足1000次的。解决这个问题可以使用lock关键字实现加锁。 lock(this){for(....)....}

    线程间传参数

    它可以传一个参数也可以传多个参数,多个参数为一个集合。但传得参数类型为object

       public void demo(object name)
            {
                MessageBox.Show("hello "+name.ToString());
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(demo);
                th.Start("chen");
            }

    多个参数:

      public void demo(object li)
            {
                List <string>list= li as List<string>;
                if (list !=null)
                {
                    foreach (var s in list)
                    {
                        MessageBox.Show(s);
                    }
                }
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(demo);
                th.Start(new List<string>() {"chen","li "});
            }

    终止线程:

    1,Abort()方法,终止已开启的线程,常用于终止永久停止的线程,一旦被终止,将无法重新启动。调用该方法时会抛出ThreadAbortException异常。

    2,Join()方法,用来阻止调用该线程,直到某一个线程终止为止。

    线程优先级,也就是在多个线程并发是,控制谁先谁后。

  • 相关阅读:
    曹工说Redis源码(8)--面试时,redis 内存淘汰总被问,但是总答不好
    曹工说JDK源码(4)--抄了一小段ConcurrentHashMap的代码,我解决了部分场景下的Redis缓存雪崩问题
    曹工说JDK源码(3)--ConcurrentHashMap,Hash算法优化、位运算揭秘
    曹工说JDK源码(2)--ConcurrentHashMap的多线程扩容,说白了,就是分段取任务
    曹工说JDK源码(1)--ConcurrentHashMap,扩容前大家同在一个哈希桶,为啥扩容后,你去新数组的高位,我只能去低位?
    曹工说Spring Boot源码(29)-- Spring 解决循环依赖为什么使用三级缓存,而不是二级缓存
    曹工说mini-dubbo(2)--分析eureka client源码,想办法把我们的服务提供者注册到eureka server(上)
    @Spring Boot程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码
    python处理txt大文本文件
    Matlab读写文件时的定位
  • 原文地址:https://www.cnblogs.com/anyihen/p/5507003.html
Copyright © 2011-2022 走看看