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:各種同步類,並發類

待補充

 

一旦開始並發了,還有很多很多的坑


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM