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

      C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。
      除非被指定,否则所有的例子都假定以下命名空间被引用了:

    using System;
    using System.Threading;
    

    C#开启线程的方法有:

    • 异步委托
    • 通过Thread类
    • 线程池
    • 任务

      总的来说其实线程的开启基本都涉及到委托的使用。

    一、异步委托开启线程

    首先来看一个比较简单的例子,采用第一种开启线程的方法——异步委托

    using System;
    using System.Threading;
    
    namespace Study
    {
        class Program
        {
            static void test()
            {
                Console.WriteLine("TestThread");
            }
            static void Main(string[] args)
            {
                Action a = test;
                a.BeginInvoke(null, null);
                Console.WriteLine("MainThread");
                Console.ReadLine();
            }
        }
    }
    

      编译运行,发现结果与预期有所不同。结果如下图
    Thread
      如果按着逐行运行代码的方式,那么应该是先输出TestThread,但是结果却是先输出MainThread。
      将a.BeginInvoke(null,null);Console.WriteLine("MainThread");对调位置之后,结果和之前的依然一致。这就说明,异步委托开启的线程是和主线程同时同步进行的。
      Action委托是指向一个没有返回值的函数,那么假设一个线程,我们需要取得他的返回结果并输出,那么就要用到Func委托。
      看下面的源码

    using System;
    using System.Threading;
    
    namespace SummerStudy
    {
        class Program
        {
            static string test(int i, string str)
            {
                Console.WriteLine("TestThread" + "	参数i是:" + i);
                return str;
            }
            static void Main(string[] args)
            {
                Func<int, string, string> a = test;
                IAsyncResult res = a.BeginInvoke(1, "返回值", null, null);
                string o = a.EndInvoke(res);
                Console.WriteLine("MainThread	" + "线程返回值是:" + o);
                Console.ReadLine();
            }
    }
    

    Thread
    同时异步委托开启线程中,判断线程是否结束的方法也有两种,一种是利用IAsyncResult的IsCompleted方法,一种是使用方法进行线程结束判断。
      具体使用方法如下。

    1. IsCompleted(bool)
    IAsyncResult ia = a.BeginInvoke()
    if(ia.IsCompleted == false)
    {
        //GoOn
    }
    
    1. AsyncWaitHandle
    IAsyncResult ia = a.BeginInvoke()
    ia.AsyncWaitHandle.WaitOne(Time);//Time为等待时间,超时后才会运行下一行代码,未完成直接跳出返回false
    

      或者通过自定义方法,BeginInvoke中倒数第二个参数是一个委托,传递一个函数,在线程结束之后会自动的调用。

    static string Test(int a)
    {
    
    }
    Func<int, string> a = Test;
    IAsyncResult ia = a.BeginInvoke(100, CallBack, a);
    static void CallBack(IAsyncResult ar)
    {
        Func<int, string> a = ia.AsyncState as Func<int, string>;
        string res = a.EndInvoke(ar);
    }
    

      在使用Lambda表达式作为委托的时候,最后一个参数可以为空,因为Lambda表达式可以访问外部变量。

    二、使用Thread类开启线程

      使用Thread类创建一个实例,它的构造方法中需要传递一个委托。通过委托绑定线程。
      直接上代码

    using System;
    using System.Threading;
    
    namespace Study
    {
        class Program
        {
            static void test()
            {
                Console.WriteLine("Thread");
                Thread.Sleep(2000);
                Console.WriteLine("TimeOver");
            }
            static void Main(string[] args)
            {
                Thread t = new Thread(test);
                t.Start();
                Console.WriteLine("Main");
                Console.Read();
            }
        }
    }
    

    Thread
      对于需要传递参数的委托,则必须制定参数类型为object,在线程Start方法中传递参数

    namespace SummerStudy
    {
        class Program
        {
            static void test(object c)
            {
                int id = Thread.CurrentThread.ManagedThreadId;
                Console.WriteLine("Thread,	线程id为" + id + ",	参数是:" + c);
                Thread.Sleep(2000);
                Console.WriteLine("TimeOver");
    
            }
            static void Main(string[] args)
            {
                Thread t = new Thread(test);
                t.Start("xxx.avi");
                Console.WriteLine("Main");
                Console.Read();
            }
        }
    }
    

    Thread
      当然你也可以自定义一个类,在类中自定义数据传递。

    三、线程池

      这种方法有助于节省时间,具体使用方法如下

    using System;
    using System.Threading;
    
    namespace SummerStudy
    {
        class Program
        {
            static void test(object c)
            {
                int id = Thread.CurrentThread.ManagedThreadId;
                Console.WriteLine("Thread,	线程id为" + id + ",	参数是:" + c);
                Thread.Sleep(2000);
                Console.WriteLine("TimeOver");
    
            }
            static void Main(string[] args)
            {
                ThreadPool.QueueUserWorkItem(test, "asfasf");
                Console.Read();
            }
        }
    }
    

      其中委托必须要有一个参数,无论是否使用该参数。且只适用于使用时间短的线程,不能改变优先级

    四、任务

      使用Task类开启线程,还有TaskFactory创建
      Task类实例

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace SummerStudy
    {
        class Program
        {
            static void test(object c)
            {
                int id = Thread.CurrentThread.ManagedThreadId;
                Console.WriteLine("Thread,	线程id为" + id);
                Thread.Sleep(2000);
                Console.WriteLine("TimeOver");
    
            }
            static void Main(string[] args)
            {
                Task t = new Task(test, "Asfgasg");
                t.Start();
    
                //或者
    
                TaskFactory tf = new TaskFactory();
    
                Task t1 = tf.StartNew(test);
                Console.Read();
            }
        }
    }
    

    我的掘金:WarrenRyan

    我的简书:WarrenRyan

    欢迎关注我的博客获得第一时间更新 https://blog.tity.xyz

    我的Github:WarrenRyan

    我的博客园:WarrenRyan

  • 相关阅读:
    值得学习:低成本创业的成功案例
    观川剧变脸绝技有感
    庸人、常人、能人和人才,你是哪一种?
    游黄浦江有感
    首出四川有感
    一个容易被人遗忘的管理技巧
    妈妈,对不起
    ora00600[kkocxj:pjpCtx]内部错误一例
    How to troubleshooting RAC Vip Problem
    TSM配置导致RMAN备份expired
  • 原文地址:https://www.cnblogs.com/WarrenRyan/p/10398669.html
Copyright © 2011-2022 走看看