• Task C# 多线程和异步模型 TPL模型


    Task,异步,多线程简单总结

    1,如何把一个异步封装为Task异步

    Task.Factory.FromAsync

    对老的一些异步模型封装为Task

    TaskCompletionSource

    更通用,在回调中只要SetResult()一下就表示Task结束了,用它可以将各种异步回调封装为Task

    2,一个可以await的可以返回Task的Async结尾的异步方法从哪里开始进入另一个线程的

    如果是对BeginXXX EndXXX的APM异步模型封装的,从进入XXXAsync方法后直到BeginXXX前还在调用方法的线程内,然后无阻塞的等待回调,当等打完后,就相当于在回调中了,此时可能进入了另一个线程,其他也是类似的,从底层方法异步的地方开始异步的,而不是一进入方法就到了另一个线程了,所以进入方法后写很多CPU密集程序是会阻塞的

    3,如何立刻扔到另一个线程

    Task.Run或者Task.Factory.StartNew可以直接从另一个线程开始,可以直接把XXXAsync方法扔进去

    4,一个约定

    纯C#框架或者类库提供的Async结尾的可await方法,里面一定有无阻塞异步的实现,否则没必要搞成异步的,就比如newtonsoft.json的异步序列化方法被标识为已过时。

    5,Task外面如何告诉Task该取消了

    CancellationTokenSource

    其实和一个Flag差不多,只不过封装了一些方法以异常类

    6,很多情况下要先学会同步才能并发

    7,Task.Run Task.Start Task.Factory.StartNew 等都是使用线程池的线程

    8,IO异步底层为IRP消息,通常是和硬件交互所使用的消息机制,当然那是驱动层的事情,IO异步当然也就是无阻塞的,等IRP消息回来就是回调

    9,UI线程

    最终会渲染界面的代码一定要在UI线程执行,可以使用比如winform的control.Invoke ,wpf的Dispatcher ,  还有利用SynchronizationContext

    10,异常处理

                var checkT1 = Task.Run(async () =>
                {
                    throw new Exception("1");
                    throw new Exception("2");
                });
    
                try
                {
                    await checkT1;
                }
                catch (AggregateException ex)
                {
                    ex.Flatten();
                    foreach (var item in ex.InnerExceptions)
                    {
                        MessageBox.Show("show1:" + item.Message);
                    }
    
                }
                catch (Exception ex2)
                {
                    MessageBox.Show("show2:" + ex2.Message);
                }
                var checkT1 = Task.Run(() =>
                {
                    throw new Exception("1");
                    throw new Exception("2");
                });
    
                try
                {
                    await checkT1;
                }
                catch (AggregateException ex)
                {
                    ex.Flatten();
                    foreach (var item in ex.InnerExceptions)
                    {
                        MessageBox.Show("show1:" + item.Message);
                    }
    
                }
                catch (Exception ex2)
                {
                    MessageBox.Show("show2:" + ex2.Message);
                }

    以上两种,输出 show2:1,也就是立即抛出原来的异常,在等待时可捕获

               var checkT1 = Task.Run(async () =>
                {
                    throw new Exception("1");
                    throw new Exception("2");
                });
    
                try
                {
                     checkT1.Wait();
                }
                catch (AggregateException ex)
                {
                    ex.Flatten();
                    foreach (var item in ex.InnerExceptions)
                    {
                        MessageBox.Show("show1:" + item.Message);
                    }
    
                }
                catch (Exception ex2)
                {
                    MessageBox.Show("show2:" + ex2.Message);
                }
    
                var checkT1 = Task.Run(() =>
                {
                    throw new Exception("1");
                    throw new Exception("2");
                });
    
                try
                {
                     checkT1.Wait();
                }
                catch (AggregateException ex)
                {
                    ex.Flatten();
                    foreach (var item in ex.InnerExceptions)
                    {
                        MessageBox.Show("show1:" + item.Message);
                    }
    
                }
                catch (Exception ex2)
                {
                    MessageBox.Show("show2:" + ex2.Message);
                }

    以上两种 Show1:1 ,也就是进入AggregateException异常处理

                var checkT1 = Task.Factory.StartNew(async () =>
                {
                    throw new Exception("1");
                    throw new Exception("2");
                });

    会吞掉异常

    此时需要用GetAwaiter

    12:各种同步类,并发类

    待补充

    一旦开始并发了,还有很多很多的坑

  • 相关阅读:
    linux上java和golang环境变量的设置
    MySQL踩坑及MySQL解压版安装
    Mysql踩坑 自动更新的时间只允许有一个
    从零开始学习PYTHON3讲义(十五)让画面动起来
    从零开始学习PYTHON3讲义(十四)写一个mp3播放器
    从零开始学习PYTHON3讲义(十三)记事本的升级版:网络记事本
    从零开始学习PYTHON3讲义(十二)画一颗心送给你
    从零开始学习PYTHON3讲义(十一)计算器升级啦
    从零开始学习PYTHON3讲义(十)自己做一个“电子记事本”
    从零开始学习PYTHON3讲义(九)字典类型和插入排序
  • 原文地址:https://www.cnblogs.com/gxrsprite/p/6102828.html
Copyright © 2020-2023  润新知