• C#多线程技术总结(异步)


    我这里针对现有的C#多线程技术进行一个汇总,一是复习,二是方便索引,文章部份知识点来源于网络,非本人原创。
    
    一、并行(异步):
    
    1.System.Threading.Tasks命名空间下的(TPL):
    
    1.1:Parallel.Invoke --并行执行多个任务,主线程等待并行执行完毕后才开始续续运行。
    
    示例:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    static void Main(string[] args)
    {
        Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism=2},Run1,Run2);
        Console.WriteLine("我是主线程!");
        Console.Read();
    }
     
    static void Run1()
    {
        Console.WriteLine("我是任务一,我运行3s");
        Thread.Sleep(3000);
        Console.WriteLine("任务一执先完成");
    }
     
    static void Run2()
    {
        Console.WriteLine("我是任务二,我运行5s");
        Thread.Sleep(5000);
        Console.WriteLine("任务二执先完成");
    }
    1.2:Parallel.For--循环迭代多个任务,多个任务之间存在并行情况,主线程等待循环迭代的多个任务执行完毕后才开始续续运行。
    
    示例:
    
    1
    2
    3
    4
    5
    Parallel.For(0, 10, (i) => {
                    Console.WriteLine("我是第{0}个任务,线程ID是:{1}",i,Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(new Random().Next(10) * 10 * 500);
                    Console.WriteLine("线程ID是:{0}执行完成", Thread.CurrentThread.ManagedThreadId);
                });
    1.3:Parallel.ForEach--循环迭代多个任务,多个任务之间存在并行情况,主线程等待循环迭代的多个任务执行完毕后才开始续续运行。注意它有多个重载方法
    
    示例:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var bag = new ConcurrentBag<int>();
     
    Parallel.ForEach(Partitioner.Create(0, 100), i =>
    {
        for (int m = i.Item1; m < i.Item2; m++)
        {
            bag.Add(m);
            Console.WriteLine("我是第{0}个任务,线程ID是:{1}", m, Thread.CurrentThread.ManagedThreadId);
        }
    });
    Console.WriteLine("并行计算:集合有:{0}", bag.Count);
    1.4:TAP(基于任务的异步编),使用Task类 (注意:默认任务开启后,会在新线程中执行,主线程不会等待任务而是继续下面的执行,若使用Task.WaitAll,则会等待相应的任务完成后才会执行)
    
    示例:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //第一种方式启动
    var task1 = new Task(() => //实例化
                {
                    Run1();
                });
     
    task1.Start(); //启动
     
     //第二种方式开启
     var task2 = Task.Factory.StartNew(() => //直接创建任务并启动
                {
                    Run2();
                });
     
    //主线程等待任务执行完
     Task.WaitAll(task1, task2);
    2.ParallelEnumerable类中的扩展方法(先将枚举对象使用AsParallel转换成ParallelQuery类型,然后就可以使用ParallelQuery在ParallelEnumerable类相关的扩展方法)
    
    示例:
    
    1
    2
    var resultList = testList.AsParallel().Where(i=>i>=100).ToList();
     Console.WriteLine("resultList Count:{0}", resultList.Count);
    3.创建新Thread--新线程启动后,主线程与创建的线程各自执行,若需要主线程等待异步线程执行完成后才执行,则应使用asyncThread.Join方法。
    
    示例:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
            static void AsyncThreadMethod()
            {
                Console.WriteLine("我是异步执行线程,线程ID是:{0}", Thread.CurrentThread.ManagedThreadId);
            }
     
            static void AsyncThreadMethod(object state)
            {
                Console.WriteLine("我是异步执行线程,线程ID是:{0},状态:{1}", Thread.CurrentThread.ManagedThreadId,state);
            }
     
     
    //创建线程并执行
                Thread asyncThread = new Thread(new ThreadStart(AsyncThreadMethod));
                asyncThread.IsBackground = true;
                asyncThread.Start();
     
                Thread asyncThread2 = new Thread(new ParameterizedThreadStart(AsyncThreadMethod));
                asyncThread2.IsBackground = true;
                asyncThread2.Start("这是来自主线程的参数");
    4.使用ThreadPool.QueueUserWorkItem静态方法--WaitCallback回调方法要求其必需带一个object的参数
    
    示例:
    
    1
    2
    3
    ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncThreadMethod));//不带参数,则系统将state自动设为null
     
    ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncThreadMethod), "这是来自主线程的参数");
    5.APM(异步编程模型),利用BeginInvoke与EndInvoke完成异步执行委托方法
    
    示例:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    Func<string, string> funcDelegate = (s) =>
    {
        Console.WriteLine("我是Func委托方法!");
        return "委托方法参数:" + s;
    };
     
    //1.无阻塞异步回调
    var aysncResult = funcDelegate.BeginInvoke("这是来自主线程的参数", new AsyncCallback((result) =>
    {
        //获取委托对象,调用EndInvoke方法获取运行结果
        AsyncResult _result = (AsyncResult)result;
        var func = (Func<string, string>)_result.AsyncDelegate;
        string data = func.EndInvoke(_result);
        Console.WriteLine(data +",附加参数:" + _result.AsyncState.ToString());
    }),"其它参数");
     
    //2.阻塞主线程,使主线程等待执行完毕
    string data2 = null;
    var aysncResult2 = funcDelegate.BeginInvoke("这是来自主线程的参数2", null, null);
     
    data2 = funcDelegate.EndInvoke(aysncResult2);//第一种阻塞方法
     
    while (!aysncResult2.IsCompleted) //第二种阻塞方法
    {
        Thread.Sleep(200);      //虚拟操作
        Console.WriteLine("主线程等待...");
    }
    data2 = funcDelegate.EndInvoke(aysncResult2);
     
    WaitHandle[] waitHandles = new WaitHandle[]{ aysncResult2.AsyncWaitHandle };
    while (WaitHandle.WaitAll(waitHandles, 5000)) //第三种阻塞方法
    {
        Console.WriteLine("主线程等待...");
    }
    6. EAP(基于事件的异步编程)--主要用在客户端应用程序中
    
    示例:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    //例子一
    var client = new WebClient();
    client.DownloadProgressChanged += delegate(object s, DownloadProgressChangedEventArgs e)
    {
        Console.WriteLine("Download Percent:{0}", e.ProgressPercentage);
    };
    client.DownloadStringCompleted += delegate(object s,DownloadStringCompletedEventArgs e){
        Console.WriteLine("Download Content Length:{0}",e.Result.Length);
        Console.WriteLine("Download Completed!");
    };
     
    client.DownloadStringAsync(new Uri("http://www.zuowenjun.cn"));
     
     
     
    //例子二
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += (s, e) => {
        Console.WriteLine("异步执行中。。。");
    };
    worker.RunWorkerCompleted += (s, e) => {
        Console.WriteLine("异步执行完成。。。");
    };
    worker.RunWorkerAsync();
    7.async和await关键字
    
    示例:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
        public Task<double> GetValueAsync(double num1, double num2)
        {
            return Task.Run(() =>
            {
                for (int i = 0; i < 1000000; i++)
                {
                    num1 = num1 / num2;
                }
                return num1;
            });
        }
        public async void DisplayValue()
        {
            double result = await GetValueAsync(1234.5, 1.01);//此处会开新线程处理GetValueAsync任务,然后方法马上返回
            //这之后的所有代码都会被封装成委托,在GetValueAsync任务完成时调用
            System.Diagnostics.Debug.WriteLine("Value is : " + result);
        }
     
    //调用
    DisplayValue();//不会阻塞主线程
  • 相关阅读:
    [转]HSPICE软件的应用及常见问题解决
    Node.js基于Express框架搭建一个简单的注册登录Web功能
    Node.js开发Web后台服务
    mysql update 将一个表某字段设为另一个表某字段的值
    一个最简的Thinkphp3.2 操作Mongodb的例子
    MongoDB GUI( Robo 3T) Shell使用及操作
    Robomongo,Mongo可视化工具
    thinkphp mysql和mongodb 完美使用
    大型网站系统架构演化之路
    30个php操作redis常用方法代码例子
  • 原文地址:https://www.cnblogs.com/profession/p/5511844.html
Copyright © 2020-2023  润新知