C# 看懂這100+行程式碼,你就真正入門了(經典)

老鐵

先不廢話,簡單粗暴,直接來原始碼:

using

System;

using

System。Collections。Concurrent;

using

System。Collections。Generic;

using

System。Threading;

using

System。Threading。Tasks;

using

System。Windows。Forms;

namespace

TestConsole

{

class

Program

{

private

static

ManualResetEvent manualResetEvent =

new

ManualResetEvent(

false

);

//AutoResetEvent略去

//private static List list = new List();//非執行緒安全,“集合已修改;可能無法執行列舉操作。”

private

static

ConcurrentBag<

int

> list =

new

ConcurrentBag<

int

>();

private

static

CancellationTokenSource cancellationToken =

new

CancellationTokenSource();

private

static

ConcurrentDictionary<

int

string

> concurrentDictionary =

new

ConcurrentDictionary<

int

string

>();

private

static

ConcurrentQueue<

int

> concurrentQueue =

new

ConcurrentQueue<

int

>();

static

void

Main

string

[] args

{

try

{

//ThreadSafetyTest();

//ManualResetEventHandler();

//DelegateTest();

TasKTest();

Console。ReadKey();

}

catch

(Exception ex)

{

MessageBox。Show(ex。StackTrace +

“ ”

+ ex。Message);

}

}

#

region

TASK用法舉例

static

void

TasKTest

{

//帶返回值的task

Task mytask = Task。Run(

async

() =>

{

await

Task。Delay(

5000

);

return

“老鐵666”

}, cancellationToken。Token);

//cancellationToken。Cancel();

while

(!mytask。Wait(

100

))

//在指定時間執行完成就返回true

{

Console。Write(

“。”

);

}

Console。WriteLine(mytask。Result);

//task任務取消,所以獲取task。Result會報錯

Task taskFactory = Task。Factory。StartNew(() =>

{

Thread。Sleep(

1000

);

Console。WriteLine(

“perfect!”

);

});

Console。WriteLine(taskFactory。Status);

taskFactory。Wait();

//taskFactory任務完成才往下執行

Task。WaitAll(mytask, taskFactory);

//所有任務完成再往下執行

Task。WaitAny(mytask, taskFactory);

//任一任務完成就往下執行

Console。WriteLine(taskFactory。Status);

Task taskTest = taskFactory。ContinueWith(DoOnSecond);

//ContinueWith用法舉例

}

static

void

DoOnSecond

Task t

{

Console。WriteLine(

“task {0} finished”

, t。Id);

Console。WriteLine(

“this task id {0}”

, Task。CurrentId);

Console。WriteLine(

“do some cleanup”

);

}

#

endregion

#

region

ManualResetEvent 用法舉例

private

static

void

ManualResetEventHandler

{

Thread t1 =

new

Thread(Thread1);

t1。Start();

Thread t2 =

new

Thread(Thread2);

t2。Start();

Thread。Sleep(

2000

);

manualResetEvent。Set();

Thread。Sleep(

5000

);

t1。Abort();

//放棄執行執行緒t1

Console。WriteLine(t1。ThreadState);

Console。WriteLine(t2。ThreadState);

}

static

void

Thread1

{

Console。WriteLine(manualResetEvent。WaitOne()。ToString());

//等待 manualResetEvent。Set()後執行

manualResetEvent。Reset();

// 將訊號置為初始狀態,即false

//Console。WriteLine(manualResetEvent。WaitOne()。ToString());//阻塞當前執行緒,讓他等待著

MessageBox。Show(

“Thread1 run end”

);

Parallel。For(

0

100000000

, item =>

{

Console。WriteLine(item。ToString());

});

}

static

void

Thread2

{

Console。WriteLine(manualResetEvent。WaitOne(

10000

)。ToString());

//10秒內收到 manualResetEvent。Set(),即true就往下執行,或者超過100秒,也往下執行,但是狀態依然為false

MessageBox。Show(

“Thread2 run end”

);

}

#

endregion

#

region

執行緒安全之ConcurrentBag 驗證

private

static

void

ThreadSafetyTest

{

int

count =

0

Task t =

new

Task(() =>

{

while

true

{

Thread。Sleep(

1000

);

count++;

list。Add(count);

}

});

t。Start();

Task。Run(() =>

{

while

true

{

foreach

var

item

in

list)

{

Thread。Sleep(

1000

);

Console。WriteLine(

$“

{list。Count}

);

}

}

});

}

#

endregion

public

static

void

DelegateTest

{

Func<

string

string

> RetBook =

new

Func<

string

string

>(FuncBook);

Console。WriteLine(RetBook(

“《平凡的世界》”

));

}

public

static

string

FuncBook

string

BookName

{

return

BookName;

}

}

}

上面程式碼邏輯要是全懂了,下面就可以跳過了,

沒看懂的繼續……。

① 首先,執行第一個方法

ThreadSafetyTest();

涉及知識點:

task的建立和使用;

foreach遍歷

執行緒安全集合ConcurrentBag用法

修改這裡後執行:

ThreadSafetyTest();

//ManualResetEventHandler();

//DelegateTest();

//TasKTest();

執行結果如下:

C# 看懂這100+行程式碼,你就真正入門了(經典)

這個方法體的作用主要是開了兩個執行緒,第一個執行緒每隔1秒向集合新增一個數,第二個執行緒每隔一秒,便利輸出集合。在這裡集合要是改成list的,即:

private

static

ConcurrentBag<

int

>

list

=

new

ConcurrentBag<

int

>();

改成=>

private

static

List<

int

>

list

=

new

List<

int

>();

執行過程會報錯:

非執行緒安全,“集合已修改;可能無法執行列舉操作。”

原因解釋:不管是讀還是寫,同一時刻只能做一件事情,要麼讀,要麼寫,多個執行緒對同一個集合進行讀寫操作,就難免會出現執行緒安全問題,當然你可以

用lock關鍵字,進行執行緒同步,但是效能並不是特別理想,然後我嘗試使用SynchronizedList來代替使用List達到執行緒安全的目的。但是發現效能依舊糟糕,於是查看了SynchronizedList的原始碼,發現它就是簡單的在List提供的API的基礎上加了lock,所以效能基本與list方式相差無幾。最後使用ConcurrentBag類來實現,效能有很大的改觀。

知識拓展:執行緒安全的佇列和字典:

ConcurrentDictionary<

int

string

> concurrentDictionary =

new

ConcurrentDictionary<

int

string

>();

ConcurrentQueue<

int

> concurrentQueue =

new

ConcurrentQueue<

int

>();

② 接下來,執行第二個方法

ManualResetEventHandler();

涉及知識點:

ManualResetEvent用法(和AutoResetEvent類似,區別自己去學習);

主要包括:

manualResetEvent。Reset(); manualResetEvent。Set();

manualResetEvent。WaitOne()和manualResetEvent。WaitOne(time)

Thread執行緒建立和使用;

重點解釋:

Console。WriteLine(manualResetEvent。WaitOne(10000)。ToString());10秒內收到 manualResetEvent。Set(),即true就往下執行,或者超過100秒,也往下執行,

但是狀態依然為false

最後的執行結果:

C# 看懂這100+行程式碼,你就真正入門了(經典)

③ 接下來,執行第三個方法

DelegateTest();

知識點:帶引數,帶返回值的委託

Func的用法

執行結果:

C# 看懂這100+行程式碼,你就真正入門了(經典)

總結一下 :

無返回就用action,有返回就用Func

④ 最後,執行第四個方法

DelegateTest();

涉及知識點:

task的建立和使用前面已經提供了兩種建立方式,這裡又提供了新的方式Task。Factory。StartNew(() =>{});

取消task任務之CancellationTokenSource的用法;

task的執行緒管控方法Task。。Wait(time),Task。WaitAll(), Task。WaitAny(),task。ContinueWith。

執行結果:

C# 看懂這100+行程式碼,你就真正入門了(經典)

原創不易,用100+行程式碼串接這麼多重要知識點更加不易。

老鐵666

老鐵到底溜不溜,在看轉發走起來!

進技術交流群的,加小編微信zls20210502,切記備註:進群!

專案工程下載地址:

連結: https://pan。baidu。com/s/1MEm-CjQjrReP6jxyqpLjQA

提取碼: wr3n

技術群: 需要進技術群的新增小編微信mm1552923,備註:加群;