• C#中异步多线程的实现方式


    线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

    一.通过委托的方式

    委托中的Invoke方法完成一个委托方法的封送,在Invoke封送的方法被执行完毕前,Invoke方法不会返回,从而调用者线程将被阻塞。委托中的BeginInvoke方法是从ThreadPool取出一个线程来执行这个方法,以获得异步执行效果的。

            public delegate int AddDelegate(int a, int b);  //定义一个委托对象
            static void Main(string[] args)
            {
                Console.WriteLine("start");
                AddDelegate d1 = Add;
                //异步回调方法,异步方法执行完可以选择执行这个方法
                AsyncCallback cab = t =>
                {
                    //Console.WriteLine(d1.EndInvoke(t));
                    Console.WriteLine(t.AsyncState);    //可以获取传递过来的参数
                    Console.WriteLine(t.IsCompleted);
                };
    
                IAsyncResult ar = d1.BeginInvoke(5,2,cab,12);    //前两个参数为引用方法传递的参数,cab为上面的回调方法,12为回调方法中的参数,执行BeginInvoke会返回一个IAsyncResult对象        
                Thread.Sleep(2000);
                int result = d1.EndInvoke(ar);           //该方法返回委方法中的真正返回值,该方法会阻塞主线程一直到异步执行完,EndInvoke只能被执行一次 
                Console.WriteLine("结果:"+result);
    
            }
            public static int Add(int a,int b)
            {
                return a + b;
            }       

     二.通过Thread类

     C#中的Thread类主要提供四个构造方法,ThreadStart是一个无参的委托,意味着我们能传递一个无参的方法进去。ParameterizedThreadStart是一个只有一个参数,参数类型为object的委托,我们可以传一个一个参数,参数类型为object的类型进去

         static void Main(string[] args)
            {
                //ThreadStart start1 = AddNoParms;
                //Thread thread1 = new Thread(start1);
                Thread thread1 = new Thread(AddNoParms);  //简化写法,直接传递与委托方法签名对应的方法
                Thread thread2 = new Thread(AddHasParms); //有参的形式
                thread1.Start();//开启这个线程
                thread2.Start("thread2");  //开启有参的Thread线程
                thread1.Name = "thread1";       //获取或设置线程的名称。
                thread1.IsBackground = true;   //获取或设置一个值,该值指示某个线程是否为后台线程。
                Thread.Sleep(2000); //让线程暂停一段时间。
                thread1.Abort();    //销毁线程
                Console.WriteLine(thread1.IsAlive);     //获取线程状态
    
    
                //获取异步回调的返回值
                int returndata = 0;     //声明一个变量用来接收异步方法执行的返回值
                ThreadStart threadstart = new ThreadStart
                    (() =>{
                            returndata = Add(1, 2);
                            AddNoParms();
                        });
                Thread thread3 = new Thread(threadstart);
                thread3.Start();
                Console.WriteLine(returndata);
            }
            public static void AddHasParms(object str)
            {
                Console.WriteLine(str);
            }
    
            public static void AddNoParms()
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine("add");
            }
            public static int Add(int a,int b)
            {
                return a + b;
            }

     Thread类中还提供了许多属性和方法供我们使用

      //属性
          IsAlive   //获取一个值,该值指示当前线程的执行状态。
          IsBackground   //获取或设置一个值,该值指示某个线程是否为后台线程。前台进程跟后台进程的区别:程序关闭时,后台线程直接关闭,但前台线程会执行完后关闭。通过Thread类新建线程默认为前台线程。其他方式创建的都是后台线程。
          IsThreadPoolThread    //获取一个值,该值指示线程是否属于托管线程池。
          Priority    //获取或设置一个值,该值指示线程的调度优先级。
      //方法
          Abort    //在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。调用此方法通常会终止线程。
          Join       //阻塞调用线程,直到某个线程终止为止。此方法有不同的重载形式
          ResetAbort    //取消为当前线程请求的 Abort。

     三.ThreadPool

    ThreadPool类会在线程的托管池中重用已有的线程,一个应用程序最多只能有一个线程池,可以通过QueueUserWorkItem方法将工作函数排入进程池。QueueUserWorkItem有两个构造函数,WaitCallback是一个只有一个参数,参数类型为object的委托,我们可以传一个参数,参数类型为object的对象进行实例化

         static void Main(string[] args)
            {
                //调用方式一  用WaitCallback这个委托进行实例化
                WaitCallback waitCallback = new WaitCallback(AddHasParms);
                ThreadPool.QueueUserWorkItem(waitCallback, "helloworld");
                //调用方式二  传递与WaitCallback对应的方法进行实例化
                ThreadPool.QueueUserWorkItem(AddHasParms,"helloworld");
                //调用方法三  通过WaitCallback相对应的匿名方法,在匿名方法中进行调用
                ThreadPool.QueueUserWorkItem(n=> {
                                AddNoParms();
                                AddHasParms("helloworld");
                           });
            }
            public static void AddHasParms(object str)
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine(str);
            }
    
            public static void AddNoParms()
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            }

     四.Task

         static void Main(string[] args)
            {
                //方式一   无返回值时
                Task task1 = new Task(AddHasParms, "helloworld");
                task1.Start();
                Task.WaitAll(task1);    //等待所有任务结束  
                        //有返回值时
                Task<int> task2 = new Task<int>(Add, "obj");
                task2.Start();
                Console.WriteLine(task2.Result);       //打印返回值
    
                //方式二    通过Run方法创建  无返回值
                Task.Run(() => AddHasParms("hello"));
                //无返回值时
                Task<int> task3 = Task.Run(() => Add("obj"));
                Console.WriteLine(task3.Result);
    
                //方式三 无返回值时
                Task.Factory.StartNew(() => AddHasParms("helloworld"));
                Task.WaitAll();
                //有返回值时
                var task4=Task.Factory.StartNew(() => Add("obj"));
                Console.WriteLine(task4.Result);
    
    
            }
            public static void AddHasParms(object str)
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                Console.WriteLine(str);
            }
            public static int Add(object a)
            {
                return  1;
            }
  • 相关阅读:
    简单的签到日历
    CSS样式命名整理
    Vue 数组中更新属性值后,视图不更新,等待其他元素更新后会触发的解决办法
    linux之cp/scp命令+scp命令详解
    js 进制转换
    博主QQ
    JSP的介绍及语法详解
    通过jdbc连接MySql数据库的增删改查操作
    在JAVA中自定义连接数据库的工具类
    通过sql语句对MySql数据库的基本操作
  • 原文地址:https://www.cnblogs.com/HTLucky/p/13441408.html
Copyright © 2020-2023  润新知