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:各种同步类,并发类

待补充

 

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

posted @ 2016-11-25 19:54  咖喱gg  阅读(1877)  评论(1编辑  收藏  举报