1. 程式人生 > 實用技巧 >非同步方法和TPL: async / await / Parallel

非同步方法和TPL: async / await / Parallel

封裝

我們要把上面這個Task封裝成方法,怎麼辦?

最重要的一點,這個方法要能返回生成的random,後面的程式碼要用!

    public static Task<int> getRandom()
    {
        return Task<int>.Run(() =>
        {
            Thread.Sleep(500);    //模擬耗時
            return new Random().Next();
        });
    }

@想一想@:應該如何呼叫這個方法?(提示:不要直接getRandom().Result

假如我們還需要進一步的封裝,新增一個方法Process,裡面呼叫getRandom()並把其結果輸出:

    public static void Process()
    {
        Task<int> task = getRandom();
        Console.WriteLine(task.Result);
    }

故技重施,好像不行了,這次……

@想一想@:再讓Process()返回Task行不行?一個Task套另一Task會出現什麼情況?

在getRandom()和Process()中展示執行緒Id看一看:

    Console.WriteLine("in getRandom() with Thread-" + Thread.CurrentThread.ManagedThreadId);

在.NET core的I/O類庫中,我們會發現這樣的方法:

    public static Task AppendAllLinesAsync(string path, IEnumerable<string> contents, Encoding encoding, CancellationToken cancellationToken = default); 
    public static Task<byte[]> ReadAllBytesAsync(string path, CancellationToken cancellationToken = default);

注意:

  • 方法名被添加了Async字尾(推薦命名規範)
  • 方法的返回型別為Task或Task<T>

非同步方法

.NET為我們提供了簡潔優雅的非同步方法,只需要兩個關鍵字:

async和await

被async標記的方法被稱為非同步方法,

  • 但是,async不一定(沒有強制力保證)非同步。同步的方法一樣可以標記async。async的作用只是:
  • 告訴編譯器方法中可以出現await。如果只有async沒有await,報編譯時警告

只有await沒有async,報編譯錯誤。

    static async void Process()
    {
        int random = await getRandom();
        Console.WriteLine(random);
    }

await,可以理解為:非同步(async)等待,後接 awaitable 例項。

我們可以簡單的把awaitable理解成Task。

非阻塞等待

非同步方法一直同步執行,直到 await。

從 await 開始非同步(分叉):

  • 執行 awatable 中的內容,同時
  • 返回方法的呼叫處,執行其後內容

直到 awaitable 中內容執行完畢,才暫停方法呼叫處內容,繼續執行await之後的程式碼。

非同步方法執行完畢,繼續方法呼叫處內容。

以上述程式碼為例:

    //33 --> 44 --> 45                      --> 46 --> 47 -->                   呼叫非同步方法處
    //                  +--> 52 --> 57-- +                                      被呼叫非同步方法
    //                  +--> 35 --> 38                        +--> 39           awaitable

注意:如果52行之前還有普通(非非同步)程式碼,這些程式碼不會被非同步執行。

await不像Wait()或Result一樣,

開始(但不是立即或同步的)
async和await會不會開啟一個新的任務(或者執行緒)?不會。

非同步方法分為兩種:

返回 void 或 Task

        public static async void Getup()
        {
            Console.WriteLine($"before await-1 with thread {Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine($"before await-2 with thread {Thread.CurrentThread.ManagedThreadId}");
            //await 之前的程式碼,在主執行緒上執行

            //
            await Task.Run(()=> {
                Console.WriteLine($"in await with thread {Thread.CurrentThread.ManagedThreadId}");
            });

            //
            Console.WriteLine($"after await-3 with thread {Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine($"after await-4 with thread {Thread.CurrentThread.ManagedThreadId}");
        }

從await開始,程式碼開始分叉(只是非同步,不一定新開執行緒):

  • 一邊執行await後的表示式(Task)
  • 一邊返回到方法呼叫者處繼續執行

直到await後的Task執行完畢,才會返回async方法,繼續執行其await(非阻塞)之後的剩餘程式碼。

            Console.WriteLine($"before async-1 with thread {Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine($"before async-2 with thread {Thread.CurrentThread.ManagedThreadId}");
            Getup();
            for (int i = 0; i < 10; i++)
            {
                //Getup()裡await部分的執行,會打亂這裡程式碼的同步執行
                Console.WriteLine($"after async-{3 + i} with thread {Thread.CurrentThread.ManagedThreadId}");
            }

實質上,await採用的是Task的ContinueWith()機制:await 之後的方法內程式碼,被 await Task 執行完畢後呼叫。

對比演示:

  • 非非同步方法:只有Task非同步執行
  • 呼叫Wait()的非非同步方法:Wait()會阻塞當前執行緒進行等待

非同步方法中的 void 可以被直接替換成 Task(推薦),以便於該方法進一步的被 await 傳遞。

void通常做為頂級(top-level)方法使用。

思考:當async方法中丟擲異常,void方法和Task方法的區別?

返回Task<T>

返回值被Task包裹,寫成Task<T>,T指方法體內宣告返回的型別

        //方法的宣告:返回的是Task<int>
        public static async Task<int> Getup()
        {
            int result = await Task<int>.Run(() =>
            {
                Thread.Sleep(500);
                Console.WriteLine($"at await in Getup() with thread {Thread.CurrentThread.ManagedThreadId}");
                return new Random().Next();
            });

            //方法體內,返回的是int
            return result;
        }

特別注意:不能直接Getup().Result 或 await Getup()取值,否則……

思考:和直接返回Task<T>的區別?

任務並行庫TaskParallelLibrary

.NET中System.Threading 和System.Threading.Tasks名稱空間下的類庫

簡化非同步/並行開發,在底層實現:

  • 動態調整並行規模
  • 處理分割槽
  • 執行緒(池)排程(器)等……

於Task的並行

最簡單的例子,Parallel.Invoke():

            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine();  Parallel.Invoke(
                    () =>
                    {
                        Console.WriteLine(i + $":task-{Task.CurrentId} in thread-{Thread.CurrentThread.ManagedThreadId}");
                        Console.WriteLine($"task-{Task.CurrentId} begin in thread-{Thread.CurrentThread.ManagedThreadId}");
                        Console.WriteLine($"task-{Task.CurrentId} in thread-{Thread.CurrentThread.ManagedThreadId}");
                        Console.WriteLine($"task-{Task.CurrentId} end in thread-{Thread.CurrentThread.ManagedThreadId}");
                    },
                    () =>
                    {
                        Console.WriteLine(i + $":task-{Task.CurrentId} in thread-{Thread.CurrentThread.ManagedThreadId}");
                        Console.WriteLine($"task-{Task.CurrentId} in begin in thread-{Thread.CurrentThread.ManagedThreadId}");
                        Console.WriteLine($"task-{Task.CurrentId} in thread-{Thread.CurrentThread.ManagedThreadId}");
                        Console.WriteLine($"task-{Task.CurrentId} in end in thread-{Thread.CurrentThread.ManagedThreadId}");
                    }
                );
            }

其他方法:

  • For迴圈
    Parallel.For(0, 10, x => { Console.WriteLine(x); });
  • ForEach
                Parallel.ForEach(Enumerable.Range(1,10), x => Console.WriteLine(x));

引入執行緒陣列:Task[]

  • WaitAll / WaitAny:
  • WhenAll / WhenAny:

對比以下程式碼,體會 await 的 continuation:

 public static async Task Getup()
        {
            //await Task.Run(() => { Console.WriteLine("洗臉"); });
            //await Task.Run(() => { Console.WriteLine("刷牙"); });
            //await Task.Run(() => { Console.WriteLine("吃早餐"); });
            //await Task.Run(() => { Console.WriteLine("背單詞"); });

            Task[] tasks =
            {
                Task.Run(() => { Console.WriteLine("洗臉"); }),
                Task.Run(() => { Console.WriteLine("刷牙"); }),
                Task.Run(() => { Console.WriteLine("吃早餐"); }),
                Task.Run(() => { Console.WriteLine("背單詞"); })
            };
            await Task.WhenAll(tasks);
        }

補充:

Delay()

FromResult()

AsyncState

並行LinqParallel LINQ (PLINQ)

僅適用於Linq to Object,主要的措施是:對資料來源進行分割槽,然後多核併發執行(保守模式:如果能不併發就不併發)

核心方法:AsParallel(),在資料來源後新增。

            try
            {
                IEnumerable<int> numbers = Enumerable.Range(0, 1000);
                var filtered = numbers.AsParallel()
                    //.Where(n => n % 11 == 0)
                    .Where(n => 8 % (n > 100 ? n : 0) == 0)
                    ;

                filtered.ForAll(f => Console.WriteLine(f));
            }
            catch (AggregateException ae)
            {
                ae.Handle(e =>
                {
                    Console.WriteLine(e);
                    return true;
                });
            }

ForAll():同樣可以併發執行

仍然是AggregateException異常

最佳實踐

使用非同步/並行的副作用(side effect):

  1. 增加程式碼的複雜性(尤其是bug除錯)
  2. 非同步/並行的切換需要消耗額外的資源

簡單理解:

  • 鎖、死鎖(Deadlock)、資源爭奪(race condition)
  • 執行緒安全 (Thread Safty)
  • 天下沒有免費的午餐
  • 越是複雜精巧的東西越不“耐操”(健壯性robust)

總是最後考慮非同步/並行:(個人建議)

    • 總是在最後考慮非同步/併發(尤其是B/S架構)
    • 確定性能瓶頸
    • 確定該瓶頸可以通過非同步/並行的方法解決

https://github.com/users/wyx9091/projects/1 https://www.github.com/users/wyx9091/projects/1 https://github.com/users/wyx9091/projects/2 https://www.github.com/users/wyx9091/projects/2 https://github.com/users/wyx9091/projects/3 https://www.github.com/users/wyx9091/projects/3 https://github.com/users/wyx9091/projects/4 https://www.github.com/users/wyx9091/projects/4 https://github.com/users/wyx9091/projects/5 https://www.github.com/users/wyx9091/projects/5 https://github.com/users/wyx9091/projects/6 https://www.github.com/users/wyx9091/projects/6 https://github.com/users/wyx9091/projects/7 https://www.github.com/users/wyx9091/projects/7 https://github.com/users/wyx9091/projects/8 https://www.github.com/users/wyx9091/projects/8 https://github.com/users/wyx9091/projects/9 https://www.github.com/users/wyx9091/projects/9 https://github.com/users/wyx9091/projects/10 https://www.github.com/users/wyx9091/projects/10 https://github.com/users/wyx9091/projects/11 https://www.github.com/users/wyx9091/projects/11 https://github.com/users/wyx9091/projects/12 https://www.github.com/users/wyx9091/projects/12 https://github.com/users/wyx9091/projects/13 https://www.github.com/users/wyx9091/projects/13 https://github.com/users/wyx9091/projects/14 https://www.github.com/users/wyx9091/projects/14 https://github.com/users/wyx9091/projects/15 https://www.github.com/users/wyx9091/projects/15 https://github.com/users/wyx9091/projects/16 https://www.github.com/users/wyx9091/projects/16 https://github.com/users/wyx9091/projects/17 https://www.github.com/users/wyx9091/projects/17 https://github.com/users/wyx9091/projects/18 https://www.github.com/users/wyx9091/projects/18 https://github.com/users/wyx9091/projects/19 https://www.github.com/users/wyx9091/projects/19 https://github.com/users/wyx9091/projects/20 https://www.github.com/users/wyx9091/projects/20 https://github.com/users/wyx9091/projects/21 https://www.github.com/users/wyx9091/projects/21 https://github.com/users/wyx9091/projects/22 https://www.github.com/users/wyx9091/projects/22 https://github.com/users/wyx9091/projects/23 https://www.github.com/users/wyx9091/projects/23 https://github.com/users/wyx9091/projects/24 https://www.github.com/users/wyx9091/projects/24 https://github.com/users/wyx9091/projects/25 https://www.github.com/users/wyx9091/projects/25 https://github.com/users/wyx9091/projects/26 https://www.github.com/users/wyx9091/projects/26 https://github.com/users/wyx9091/projects/27 https://www.github.com/users/wyx9091/projects/27 https://github.com/users/wyx9091/projects/28 https://www.github.com/users/wyx9091/projects/28 https://github.com/users/wyx9091/projects/29 https://www.github.com/users/wyx9091/projects/29 https://github.com/users/wyx9091/projects/30 https://www.github.com/users/wyx9091/projects/30 https://github.com/users/wyx9091/projects/31 https://www.github.com/users/wyx9091/projects/31 https://github.com/users/wyx9091/projects/32 https://www.github.com/users/wyx9091/projects/32 https://github.com/users/wyx9091/projects/33 https://www.github.com/users/wyx9091/projects/33 https://github.com/users/wyx9091/projects/34 https://www.github.com/users/wyx9091/projects/34 https://github.com/users/wyx9091/projects/35 https://www.github.com/users/wyx9091/projects/35 https://github.com/users/wyx9091/projects/36 https://www.github.com/users/wyx9091/projects/36 https://github.com/users/wyx9091/projects/37 https://www.github.com/users/wyx9091/projects/37 https://github.com/users/wyx9091/projects/38 https://www.github.com/users/wyx9091/projects/38 https://github.com/users/wyx9091/projects/39 https://www.github.com/users/wyx9091/projects/39 https://github.com/users/wyx9091/projects/40 https://www.github.com/users/wyx9091/projects/40 https://github.com/users/wyx9091/projects/41 https://www.github.com/users/wyx9091/projects/41 https://github.com/users/wyx9091/projects/42 https://www.github.com/users/wyx9091/projects/42 https://github.com/users/wyx9091/projects/43 https://www.github.com/users/wyx9091/projects/43 https://github.com/users/wyx9091/projects/44 https://www.github.com/users/wyx9091/projects/44 https://github.com/users/wyx9091/projects/45 https://www.github.com/users/wyx9091/projects/45 https://github.com/users/wyx9091/projects/46 https://www.github.com/users/wyx9091/projects/46 https://github.com/users/wyx9091/projects/47 https://www.github.com/users/wyx9091/projects/47 https://github.com/users/wyx9091/projects/48 https://www.github.com/users/wyx9091/projects/48 https://github.com/users/wyx9091/projects/49 https://www.github.com/users/wyx9091/projects/49 https://github.com/users/wyx9091/projects/50 https://www.github.com/users/wyx9091/projects/50 https://github.com/users/wyx9091/projects/51 https://www.github.com/users/wyx9091/projects/51 https://github.com/users/wyx9091/projects/52 https://www.github.com/users/wyx9091/projects/52 https://github.com/users/wyx9091/projects/53 https://www.github.com/users/wyx9091/projects/53 https://github.com/users/wyx9091/projects/54 https://www.github.com/users/wyx9091/projects/54 https://github.com/users/wyx9091/projects/55 https://www.github.com/users/wyx9091/projects/55 https://github.com/users/wyx9091/projects/56 https://www.github.com/users/wyx9091/projects/56 https://github.com/users/wyx9091/projects/57 https://www.github.com/users/wyx9091/projects/57 https://github.com/users/wyx9091/projects/58 https://www.github.com/users/wyx9091/projects/58 https://github.com/users/wyx9091/projects/59 https://www.github.com/users/wyx9091/projects/59 https://github.com/users/wyx9091/projects/60 https://www.github.com/users/wyx9091/projects/60 https://github.com/users/wyx9091/projects/61 https://www.github.com/users/wyx9091/projects/61 https://github.com/users/wyx9091/projects/62 https://www.github.com/users/wyx9091/projects/62 https://github.com/users/wyx9091/projects/63 https://www.github.com/users/wyx9091/projects/63 https://github.com/users/wyx9091/projects/64 https://www.github.com/users/wyx9091/projects/64 https://github.com/users/wyx9091/projects/65 https://www.github.com/users/wyx9091/projects/65 https://github.com/users/wyx9091/projects/66 https://www.github.com/users/wyx9091/projects/66 https://github.com/users/wyx9091/projects/67 https://www.github.com/users/wyx9091/projects/67 https://github.com/users/wyx9091/projects/68 https://www.github.com/users/wyx9091/projects/68 https://github.com/users/wyx9091/projects/69 https://www.github.com/users/wyx9091/projects/69 https://github.com/users/wyx9091/projects/70 https://www.github.com/users/wyx9091/projects/70 https://github.com/users/wyx9091/projects/71 https://www.github.com/users/wyx9091/projects/71 https://github.com/users/wyx9091/projects/72 https://www.github.com/users/wyx9091/projects/72 https://github.com/users/wyx9091/projects/73 https://www.github.com/users/wyx9091/projects/73 https://github.com/users/wyx9091/projects/74 https://www.github.com/users/wyx9091/projects/74 https://github.com/users/wyx9091/projects/75 https://www.github.com/users/wyx9091/projects/75 https://github.com/users/wyx9091/projects/76 https://www.github.com/users/wyx9091/projects/76 https://github.com/users/wyx9091/projects/77 https://www.github.com/users/wyx9091/projects/77 https://github.com/users/wyx9091/projects/78 https://www.github.com/users/wyx9091/projects/78 https://github.com/users/wyx9091/projects/79 https://www.github.com/users/wyx9091/projects/79 https://github.com/users/wyx9091/projects/80 https://www.github.com/users/wyx9091/projects/80 https://github.com/users/wyx9091/projects/81 https://www.github.com/users/wyx9091/projects/81 https://github.com/users/wyx9091/projects/82 https://www.github.com/users/wyx9091/projects/82 https://github.com/users/wyx9091/projects/83 https://www.github.com/users/wyx9091/projects/83 https://github.com/users/wyx9091/projects/84 https://www.github.com/users/wyx9091/projects/84 https://github.com/users/wyx9091/projects/85 https://www.github.com/users/wyx9091/projects/85 https://github.com/users/wyx9091/projects/86 https://www.github.com/users/wyx9091/projects/86 https://github.com/users/wyx9091/projects/87 https://www.github.com/users/wyx9091/projects/87 https://github.com/users/wyx9091/projects/88 https://www.github.com/users/wyx9091/projects/88 https://github.com/users/wyx9091/projects/89 https://www.github.com/users/wyx9091/projects/89 https://github.com/users/wyx9091/projects/90 https://www.github.com/users/wyx9091/projects/90 https://github.com/users/wyx9091/projects/91 https://www.github.com/users/wyx9091/projects/91 https://github.com/users/wyx9091/projects/92 https://www.github.com/users/wyx9091/projects/92 https://github.com/users/wyx9091/projects/93 https://www.github.com/users/wyx9091/projects/93 https://github.com/users/wyx9091/projects/94 https://www.github.com/users/wyx9091/projects/94 https://github.com/users/wyx9091/projects/95 https://www.github.com/users/wyx9091/projects/95 https://github.com/users/wyx9091/projects/96 https://www.github.com/users/wyx9091/projects/96 https://github.com/users/wyx9091/projects/97 https://www.github.com/users/wyx9091/projects/97 https://github.com/users/wyx9091/projects/98 https://www.github.com/users/wyx9091/projects/98 https://github.com/users/wyx9091/projects/99 https://www.github.com/users/wyx9091/projects/99 https://github.com/users/wyx9091/projects/100 https://www.github.com/users/wyx9091/projects/100 https://github.com/users/wyx9091/projects/101 https://www.github.com/users/wyx9091/projects/101 https://github.com/users/wyx9091/projects/102 https://www.github.com/users/wyx9091/projects/102 https://github.com/users/wyx9091/projects/103 https://www.github.com/users/wyx9091/projects/103 https://github.com/users/wyx9091/projects/104 https://www.github.com/users/wyx9091/projects/104 https://github.com/users/wyx9091/projects/105 https://www.github.com/users/wyx9091/projects/105 https://github.com/users/wyx9091/projects/106 https://www.github.com/users/wyx9091/projects/106 https://github.com/users/wyx9091/projects/107 https://www.github.com/users/wyx9091/projects/107 https://github.com/users/wyx9091/projects/108 https://www.github.com/users/wyx9091/projects/108 https://github.com/users/wyx9091/projects/109 https://www.github.com/users/wyx9091/projects/109 https://github.com/users/wyx9091/projects/110 https://www.github.com/users/wyx9091/projects/110 https://github.com/users/wyx9091/projects/111 https://www.github.com/users/wyx9091/projects/111 https://github.com/users/wyx9091/projects/112 https://www.github.com/users/wyx9091/projects/112 https://github.com/users/wyx9091/projects/113 https://www.github.com/users/wyx9091/projects/113 https://github.com/users/wyx9091/projects/114 https://www.github.com/users/wyx9091/projects/114 https://github.com/users/wyx9091/projects/115 https://www.github.com/users/wyx9091/projects/115 https://github.com/users/wyx9091/projects/116 https://www.github.com/users/wyx9091/projects/116 https://github.com/users/wyx9091/projects/117 https://www.github.com/users/wyx9091/projects/117 https://github.com/users/wyx9091/projects/118 https://www.github.com/users/wyx9091/projects/118 https://github.com/users/wyx9091/projects/119 https://www.github.com/users/wyx9091/projects/119 https://github.com/users/wyx9091/projects/120 https://www.github.com/users/wyx9091/projects/120 https://github.com/users/wyx9091/projects/121 https://www.github.com/users/wyx9091/projects/121 https://github.com/users/wyx9091/projects/122 https://www.github.com/users/wyx9091/projects/122 https://github.com/users/wyx9091/projects/123 https://www.github.com/users/wyx9091/projects/123 https://github.com/users/wyx9091/projects/124 https://www.github.com/users/wyx9091/projects/124 https://github.com/users/wyx9091/projects/125 https://www.github.com/users/wyx9091/projects/125 https://github.com/users/wyx9091/projects/126 https://www.github.com/users/wyx9091/projects/126 https://github.com/users/wyx9091/projects/127 https://www.github.com/users/wyx9091/projects/127 https://github.com/users/wyx9091/projects/128 https://www.github.com/users/wyx9091/projects/128 https://github.com/users/wyx9091/projects/129 https://www.github.com/users/wyx9091/projects/129 https://github.com/users/wyx9091/projects/130 https://www.github.com/users/wyx9091/projects/130 https://github.com/users/wyx9091/projects/131 https://www.github.com/users/wyx9091/projects/131 https://github.com/users/wyx9091/projects/132 https://www.github.com/users/wyx9091/projects/132 https://github.com/users/wyx9091/projects/133 https://www.github.com/users/wyx9091/projects/133 https://github.com/users/wyx9091/projects/134 https://www.github.com/users/wyx9091/projects/134 https://github.com/users/wyx9091/projects/135 https://www.github.com/users/wyx9091/projects/135 https://github.com/users/wyx9091/projects/136 https://www.github.com/users/wyx9091/projects/136 https://github.com/users/wyx9091/projects/137 https://www.github.com/users/wyx9091/projects/137 https://github.com/users/wyx9091/projects/138 https://www.github.com/users/wyx9091/projects/138 https://github.com/users/wyx9091/projects/139 https://www.github.com/users/wyx9091/projects/139 https://github.com/users/wyx9091/projects/140 https://www.github.com/users/wyx9091/projects/140 https://github.com/users/wyx9091/projects/141 https://www.github.com/users/wyx9091/projects/141 https://github.com/users/wyx9091/projects/142 https://www.github.com/users/wyx9091/projects/142 https://github.com/users/wyx9091/projects/143 https://www.github.com/users/wyx9091/projects/143 https://github.com/users/wyx9091/projects/144 https://www.github.com/users/wyx9091/projects/144 https://github.com/users/wyx9091/projects/145 https://www.github.com/users/wyx9091/projects/145 https://github.com/users/wyx9091/projects/146 https://www.github.com/users/wyx9091/projects/146 https://github.com/users/wyx9091/projects/147 https://www.github.com/users/wyx9091/projects/147 https://github.com/users/wyx9091/projects/148 https://www.github.com/users/wyx9091/projects/148 https://github.com/users/wyx9091/projects/149 https://www.github.com/users/wyx9091/projects/149 https://github.com/users/wyx9091/projects/150 https://www.github.com/users/wyx9091/projects/150 https://github.com/users/wyx9091/projects/151 https://www.github.com/users/wyx9091/projects/151 https://github.com/users/wyx9091/projects/152 https://www.github.com/users/wyx9091/projects/152 https://github.com/users/wyx9091/projects/153 https://www.github.com/users/wyx9091/projects/153 https://github.com/users/wyx9091/projects/154 https://www.github.com/users/wyx9091/projects/154 https://github.com/users/wyx9091/projects/155 https://www.github.com/users/wyx9091/projects/155 https://github.com/users/wyx9091/projects/156 https://www.github.com/users/wyx9091/projects/156 https://github.com/users/wyx9091/projects/157 https://www.github.com/users/wyx9091/projects/157 https://github.com/users/wyx9091/projects/158 https://www.github.com/users/wyx9091/projects/158 https://github.com/users/wyx9091/projects/159 https://www.github.com/users/wyx9091/projects/159 https://github.com/users/wyx9091/projects/160 https://www.github.com/users/wyx9091/projects/160 https://github.com/users/wyx9091/projects/161 https://www.github.com/users/wyx9091/projects/161 https://github.com/users/wyx9091/projects/162 https://www.github.com/users/wyx9091/projects/162 https://github.com/users/wyx9091/projects/163 https://www.github.com/users/wyx9091/projects/163 https://github.com/users/wyx9091/projects/164 https://www.github.com/users/wyx9091/projects/164 https://github.com/users/wyx9091/projects/165 https://www.github.com/users/wyx9091/projects/165 https://github.com/users/wyx9091/projects/166 https://www.github.com/users/wyx9091/projects/166 https://github.com/users/wyx9091/projects/167 https://www.github.com/users/wyx9091/projects/167 https://github.com/users/wyx9091/projects/168 https://www.github.com/users/wyx9091/projects/168 https://github.com/users/wyx9091/projects/169 https://www.github.com/users/wyx9091/projects/169 https://github.com/users/wyx9091/projects/170 https://www.github.com/users/wyx9091/projects/170 https://github.com/users/wyx9091/projects/171 https://www.github.com/users/wyx9091/projects/171 https://github.com/users/wyx9091/projects/172 https://www.github.com/users/wyx9091/projects/172 https://github.com/users/wyx9091/projects/173 https://www.github.com/users/wyx9091/projects/173 https://github.com/users/wyx9091/projects/174 https://www.github.com/users/wyx9091/projects/174 https://github.com/users/wyx9091/projects/175 https://www.github.com/users/wyx9091/projects/175 https://github.com/users/wyx9091/projects/176 https://www.github.com/users/wyx9091/projects/176 https://github.com/users/wyx9091/projects/177 https://www.github.com/users/wyx9091/projects/177 https://github.com/users/wyx9091/projects/178 https://www.github.com/users/wyx9091/projects/178 https://github.com/users/wyx9091/projects/179 https://www.github.com/users/wyx9091/projects/179 https://github.com/users/wyx9091/projects/180 https://www.github.com/users/wyx9091/projects/180 https://github.com/users/wyx9091/projects/181 https://www.github.com/users/wyx9091/projects/181 https://github.com/users/wyx9091/projects/182 https://www.github.com/users/wyx9091/projects/182 https://github.com/users/wyx9091/projects/183 https://www.github.com/users/wyx9091/projects/183 https://github.com/users/wyx9091/projects/184 https://www.github.com/users/wyx9091/projects/184 https://github.com/users/wyx9091/projects/185 https://www.github.com/users/wyx9091/projects/185 https://github.com/users/wyx9091/projects/186 https://www.github.com/users/wyx9091/projects/186 https://github.com/users/wyx9091/projects/187 https://www.github.com/users/wyx9091/projects/187 https://github.com/users/wyx9091/projects/188 https://www.github.com/users/wyx9091/projects/188 https://github.com/users/wyx9091/projects/189 https://www.github.com/users/wyx9091/projects/189 https://github.com/users/wyx9091/projects/190 https://www.github.com/users/wyx9091/projects/190 https://github.com/users/wyx9091/projects/191 https://www.github.com/users/wyx9091/projects/191 https://github.com/users/wyx9091/projects/192 https://www.github.com/users/wyx9091/projects/192 https://github.com/users/wyx9091/projects/193 https://www.github.com/users/wyx9091/projects/193 https://github.com/users/wyx9091/projects/194 https://www.github.com/users/wyx9091/projects/194 https://github.com/users/wyx9091/projects/195 https://www.github.com/users/wyx9091/projects/195 https://github.com/users/wyx9091/projects/196 https://www.github.com/users/wyx9091/projects/196 https://github.com/users/wyx9091/projects/197 https://www.github.com/users/wyx9091/projects/197 https://github.com/users/wyx9091/projects/198 https://www.github.com/users/wyx9091/projects/198 https://github.com/users/wyx9091/projects/199 https://www.github.com/users/wyx9091/projects/199 https://github.com/users/wyx9091/projects/200 https://www.github.com/users/wyx9091/projects/200 https://github.com/users/wyx9091/projects/201 https://www.github.com/users/wyx9091/projects/201 https://github.com/users/wyx9091/projects/202 https://www.github.com/users/wyx9091/projects/202 https://github.com/users/wyx9091/projects/203 https://www.github.com/users/wyx9091/projects/203 https://github.com/users/wyx9091/projects/204 https://www.github.com/users/wyx9091/projects/204 https://github.com/users/wyx9091/projects/205 https://www.github.com/users/wyx9091/projects/205 https://github.com/users/wyx9091/projects/206 https://www.github.com/users/wyx9091/projects/206 https://github.com/users/wyx9091/projects/207 https://www.github.com/users/wyx9091/projects/207 https://github.com/users/wyx9091/projects/208 https://www.github.com/users/wyx9091/projects/208 https://github.com/users/wyx9091/projects/209 https://www.github.com/users/wyx9091/projects/209 https://github.com/users/wyx9091/projects/210 https://www.github.com/users/wyx9091/projects/210 https://github.com/users/wyx9091/projects/211 https://www.github.com/users/wyx9091/projects/211 https://github.com/users/wyx9091/projects/212 https://www.github.com/users/wyx9091/projects/212 https://github.com/users/wyx9091/projects/213 https://www.github.com/users/wyx9091/projects/213 https://github.com/users/wyx9091/projects/214 https://www.github.com/users/wyx9091/projects/214 https://github.com/users/wyx9091/projects/215 https://www.github.com/users/wyx9091/projects/215 https://github.com/users/wyx9091/projects/216 https://www.github.com/users/wyx9091/projects/216 https://github.com/users/wyx9091/projects/217 https://www.github.com/users/wyx9091/projects/217 https://github.com/users/wyx9091/projects/218 https://www.github.com/users/wyx9091/projects/218 https://github.com/users/wyx9091/projects/219 https://www.github.com/users/wyx9091/projects/219 https://github.com/users/wyx9091/projects/220 https://www.github.com/users/wyx9091/projects/220 https://github.com/users/wyx9091/projects/221 https://www.github.com/users/wyx9091/projects/221 https://github.com/users/wyx9091/projects/222 https://www.github.com/users/wyx9091/projects/222 https://github.com/users/wyx9091/projects/223 https://www.github.com/users/wyx9091/projects/223 https://github.com/users/wyx9091/projects/224 https://www.github.com/users/wyx9091/projects/224 https://github.com/users/wyx9091/projects/225 https://www.github.com/users/wyx9091/projects/225 https://github.com/users/wyx9091/projects/226 https://www.github.com/users/wyx9091/projects/226 https://github.com/users/wyx9091/projects/227 https://www.github.com/users/wyx9091/projects/227 https://github.com/users/wyx9091/projects/228 https://www.github.com/users/wyx9091/projects/228 https://github.com/users/wyx9091/projects/229 https://www.github.com/users/wyx9091/projects/229 https://github.com/users/wyx9091/projects/230 https://www.github.com/users/wyx9091/projects/230 https://github.com/users/wyx9091/projects/231 https://www.github.com/users/wyx9091/projects/231 https://github.com/users/wyx9091/projects/232 https://www.github.com/users/wyx9091/projects/232 https://github.com/users/wyx9091/projects/233 https://www.github.com/users/wyx9091/projects/233 https://github.com/users/wyx9091/projects/234 https://www.github.com/users/wyx9091/projects/234 https://github.com/users/wyx9091/projects/235 https://www.github.com/users/wyx9091/projects/235 https://github.com/users/wyx9091/projects/236 https://www.github.com/users/wyx9091/projects/236 https://github.com/users/wyx9091/projects/237 https://www.github.com/users/wyx9091/projects/237 https://github.com/users/wyx9091/projects/238 https://www.github.com/users/wyx9091/projects/238 https://github.com/users/wyx9091/projects/239 https://www.github.com/users/wyx9091/projects/239 https://github.com/users/wyx9091/projects/240 https://www.github.com/users/wyx9091/projects/240 https://github.com/users/wyx9091/projects/241 https://www.github.com/users/wyx9091/projects/241 https://github.com/users/wyx9091/projects/242 https://www.github.com/users/wyx9091/projects/242 https://github.com/users/wyx9091/projects/243 https://www.github.com/users/wyx9091/projects/243 https://github.com/users/wyx9091/projects/244 https://www.github.com/users/wyx9091/projects/244 https://github.com/users/wyx9091/projects/245 https://www.github.com/users/wyx9091/projects/245 https://github.com/users/wyx9091/projects/246 https://www.github.com/users/wyx9091/projects/246 https://github.com/users/wyx9091/projects/247 https://www.github.com/users/wyx9091/projects/247 https://github.com/users/wyx9091/projects/248 https://www.github.com/users/wyx9091/projects/248 https://github.com/users/wyx9091/projects/249 https://www.github.com/users/wyx9091/projects/249 https://github.com/users/wyx9091/projects/250 https://www.github.com/users/wyx9091/projects/250 https://github.com/users/wyx9091/projects/251 https://www.github.com/users/wyx9091/projects/251 https://github.com/users/wyx9091/projects/252 https://www.github.com/users/wyx9091/projects/252 https://github.com/users/wyx9091/projects/253 https://www.github.com/users/wyx9091/projects/253 https://github.com/users/wyx9091/projects/254 https://www.github.com/users/wyx9091/projects/254 https://github.com/users/wyx9091/projects/255 https://www.github.com/users/wyx9091/projects/255 https://github.com/users/wyx9091/projects/256 https://www.github.com/users/wyx9091/projects/256 https://github.com/users/wyx9091/projects/257 https://www.github.com/users/wyx9091/projects/257 https://github.com/users/wyx9091/projects/258 https://www.github.com/users/wyx9091/projects/258 https://github.com/users/wyx9091/projects/259 https://www.github.com/users/wyx9091/projects/259 https://github.com/users/wyx9091/projects/260 https://www.github.com/users/wyx9091/projects/260 https://github.com/users/wyx9091/projects/261 https://www.github.com/users/wyx9091/projects/261 https://github.com/users/wyx9091/projects/262 https://www.github.com/users/wyx9091/projects/262 https://github.com/users/wyx9091/projects/263 https://www.github.com/users/wyx9091/projects/263 https://github.com/users/wyx9091/projects/264 https://www.github.com/users/wyx9091/projects/264 https://github.com/users/wyx9091/projects/265 https://www.github.com/users/wyx9091/projects/265 https://github.com/users/wyx9091/projects/266 https://www.github.com/users/wyx9091/projects/266 https://github.com/users/wyx9091/projects/267 https://www.github.com/users/wyx9091/projects/267 https://github.com/users/wyx9091/projects/268 https://www.github.com/users/wyx9091/projects/268 https://github.com/users/wyx9091/projects/269 https://www.github.com/users/wyx9091/projects/269 https://github.com/users/wyx9091/projects/270 https://www.github.com/users/wyx9091/projects/270 https://github.com/users/wyx9091/projects/271 https://www.github.com/users/wyx9091/projects/271 https://github.com/users/wyx9091/projects/272 https://www.github.com/users/wyx9091/projects/272 https://github.com/users/wyx9091/projects/273 https://www.github.com/users/wyx9091/projects/273 https://github.com/users/wyx9091/projects/274 https://www.github.com/users/wyx9091/projects/274 https://github.com/users/wyx9091/projects/275 https://www.github.com/users/wyx9091/projects/275 https://github.com/users/wyx9091/projects/276 https://www.github.com/users/wyx9091/projects/276 https://github.com/users/wyx9091/projects/277 https://www.github.com/users/wyx9091/projects/277 https://github.com/users/wyx9091/projects/278 https://www.github.com/users/wyx9091/projects/278 https://github.com/users/wyx9091/projects/279 https://www.github.com/users/wyx9091/projects/279 https://github.com/users/wyx9091/projects/280 https://www.github.com/users/wyx9091/projects/280 https://github.com/users/wyx9091/projects/281 https://www.github.com/users/wyx9091/projects/281 https://github.com/users/wyx9091/projects/282 https://www.github.com/users/wyx9091/projects/282 https://github.com/users/wyx9091/projects/283 https://www.github.com/users/wyx9091/projects/283 https://github.com/users/wyx9091/projects/284 https://www.github.com/users/wyx9091/projects/284 https://github.com/users/wyx9091/projects/285 https://www.github.com/users/wyx9091/projects/285 https://github.com/users/wyx9091/projects/286 https://www.github.com/users/wyx9091/projects/286 https://github.com/users/wyx9091/projects/287 https://www.github.com/users/wyx9091/projects/287 https://github.com/users/wyx9091/projects/288 https://www.github.com/users/wyx9091/projects/288 https://github.com/users/wyx9091/projects/289 https://www.github.com/users/wyx9091/projects/289 https://github.com/users/wyx9091/projects/290 https://www.github.com/users/wyx9091/projects/290 https://github.com/users/wyx9091/projects/291 https://www.github.com/users/wyx9091/projects/291 https://github.com/users/wyx9091/projects/292 https://www.github.com/users/wyx9091/projects/292 https://github.com/users/wyx9091/projects/293 https://www.github.com/users/wyx9091/projects/293 https://github.com/users/wyx9091/projects/294 https://www.github.com/users/wyx9091/projects/294 https://github.com/users/wyx9091/projects/295 https://www.github.com/users/wyx9091/projects/295 https://github.com/users/wyx9091/projects/296 https://www.github.com/users/wyx9091/projects/296 https://github.com/users/wyx9091/projects/297 https://www.github.com/users/wyx9091/projects/297 https://github.com/users/wyx9091/projects/298 https://www.github.com/users/wyx9091/projects/298 https://github.com/users/wyx9091/projects/299 https://www.github.com/users/wyx9091/projects/299 https://github.com/users/wyx9091/projects/300 https://www.github.com/users/wyx9091/projects/300 https://github.com/users/wyx9091/projects/301 https://www.github.com/users/wyx9091/projects/301 https://github.com/users/wyx9091/projects/302 https://www.github.com/users/wyx9091/projects/302 https://github.com/users/wyx9091/projects/303 https://www.github.com/users/wyx9091/projects/303 https://github.com/users/wyx9091/projects/304 https://www.github.com/users/wyx9091/projects/304 https://github.com/users/wyx9091/projects/305 https://www.github.com/users/wyx9091/projects/305 https://github.com/users/wyx9091/projects/306 https://www.github.com/users/wyx9091/projects/306 https://github.com/users/wyx9091/projects/307 https://www.github.com/users/wyx9091/projects/307 https://github.com/users/wyx9091/projects/308 https://www.github.com/users/wyx9091/projects/308 https://github.com/users/wyx9091/projects/309 https://www.github.com/users/wyx9091/projects/309 https://github.com/users/wyx9091/projects/310 https://www.github.com/users/wyx9091/projects/310 https://github.com/users/wyx9091/projects/311 https://www.github.com/users/wyx9091/projects/311 https://github.com/users/wyx9091/projects/312 https://www.github.com/users/wyx9091/projects/312 https://github.com/users/wyx9091/projects/313 https://www.github.com/users/wyx9091/projects/313 https://github.com/users/wyx9091/projects/314 https://www.github.com/users/wyx9091/projects/314 https://github.com/users/wyx9091/projects/315 https://www.github.com/users/wyx9091/projects/315 https://github.com/users/wyx9091/projects/316