非同步方法和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()
並行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):
- 增加程式碼的複雜性(尤其是bug除錯)
- 非同步/並行的切換需要消耗額外的資源
簡單理解:
- 鎖、死鎖(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