C# 8 - using聲明 和 異步流


這兩個主題沒什么關系,但是怕文章太短被移除主頁。

using聲明

using語句塊 

盡管.NET Core運行時有垃圾收集器(GC)來負責內存清理工作,但是我們還是要自己確保當非托管資源不再使用的時候應該被清理掉。以前針對實現了IDisposable接口的對象,我們經常會使用using 語句塊來這樣做: 

class 
O references 
static void Mgin(stringC] 
gx•gs 
using (var 
= new DbConnection( 
db 
Console.WriteLine("Start using db...." 
Console.WriteLine("End of the Main method"); 
I reference 
public class DbConnection 
O references 
public void Dispose() 
IDisposable 
Console.WriteLine( "Db Connection Disposed");

 

這時候它的輸出是這樣的: 

Start using db. 
Db Connection Disposed 
End of the main method

 

這樣寫還是有一點麻煩的,能簡單一些就好了。但是而如果不使用using語句的話,那資源就不會被清理: 

Mgin(stringC] 
static void 
args 
new DbConnection( ) 
db 
var 
.WriteLine("Start using db...." 
Console 
Console.WriteLine("End of the Main method");

 

其輸出就沒有disposed那段了: 

Start using db. 
End of the main method

 

using聲明 

但是從C# 8開始,我們可以使用using聲明來做這件事了,要比之前的using語句塊簡單一些,直接看例子: 

static v 
Elgin(stringC] 
gx•gs 
= new DbConnection() 
db 
using var 
Console.WriteLine("Start using db...." 
Console.WriteLine("End of the Main method");

就是在定義變量前面的地方使用using聲明。 

 

這樣做的話,在Main方法走完的時候,db這個資源是可以被清理掉的: 

Start using db. 
End of the main method 
b Connection Disposed

可以看到db被Disposed了,但是您肯定也發現了不同之處:最后兩行輸出的順序發生了變化。 

 

在使用using語句塊的時候,清理動作發生在using塊結束的時候: 

using (var 
= new DbConnection( 
db 
Console.WriteLine("Start using db...."

 

而使用using聲明以后,清理動作會發生超出db作用范圍的時候,也就是離開Main方法的時候: 

static void Elgin(stringC] 
gx•gs 
new DbConnection() 
db 
using var 
Console.WriteLine("Start using db...." 
Console.WriteLine("End of the Main method");

 

用法

using語句塊和using聲明還是要結合具體情況來使用。。。 

更詳細內容請點擊:官方教程

 

異步流 Asynchronous Streams

例子 

private static int Threadld 
Thread . CurrentThread . ManagedThreadId ; 
O references 
static void Elgin(stringC] 
gx•gs 
new NumberFactory(); 
var factory = 
Console. WriteLine($" 
{Threadld}- 
Enumerating numbers "); 
foreach (var number in factory.GenerateNumbers( count: 5)) 
Console.WriteLine($" 
--{ThreadId} 
Console.WriteLine($" 
{Threadld}- 
{number}."), 
Received number: 
numbers received." ,

這是一個很簡單的控制台程序。它有一個NumberFactory,它可以根據傳遞的參數來產生一串數字(IEnumerable<int>)。然后在這個程序中把每個數字都打印出來,同時在前邊顯示出當前的線程ID。 

 

這里面的NumberFactory也是非常的簡單: 

public class NumberFactory 
I reference 
public IEnumerable<int> GenerateNumbers(int count) 
for (int i = 
0; i < count; 
Task. Delay(1ØØØ) .Wait(); 
yield return i + 1;

這里我做了延遲,模擬讀取外部資源的效果。 

 

運行程序(文章考不到挨個輸出的停頓效果): 

Enumerating numbers.. . 
Received number: 1.

 

Enumerating numbers.. . 
Received number: 
Received number: 
Received number: 
Received number: 
Received number: 
4. 
All numbers received .

可以看到所在線程的ID都是1。因為其工作原理就是這樣的,程序會阻塞線程以便讓NumberFactory來做它的工作。所以說這樣不是很理想,最理想的辦法是使用C#的異步編程模型,但是在C# 8之前,這是做不到的。但是從C# 8開始,我們就可以這樣做了。 

 

Asynchronous Stream異步流 

首先修改NumberFactory,在Task.Delay(1000)前邊加上await關鍵字來代替.Wait()方法,然后再修改返回類型為IAsyncEnumberable<int>,並在前面添加async關鍵字: 

public async IAsyncEnumerable<int> GenerateNumbers(int count) 
for (int i = 
0; i < count; 
await Task.Delay(1ØØØ); 
yield return i + 1;

 

回到Main方法,需要做出兩個修改: 

static async Task Mgin(stringC] 
gx•gs 
new NumberFactory(); 
var factory = 
Console.WriteLine($" 
- {Threadld}- 
Enumerating numbers "); 
await foreach (var number in factory .GenerateNumbers( count: 
5)) 
Console . WriteLine($" 
-{ThreadId} 
Console.WriteLine($" 
- {Threadld}- 
Received number: 
numbers received. 
{number}."),

首先,就是在foreach循環前面加上await關鍵字,這看起來比較奇怪,但這就是我們遍歷異步流的方式。注意是在foreach前邊加await,而不是在factory.GenerateNumbers(5)前邊加await。 

然后,還需要改變Main方法的返回類型為Task,並加上async關鍵字。 

 

最后運行程序,看看效果: 

可以看到,線程的ID有時候會發生變化,這就是我們想要的效果。在這里流是異步的,當它await任務的時候,該線程是可以去做其它工作的。而當程序繼續執行的時候,它確實可能結束於其它的線程。 

更詳細內容請點擊:官方教程


免責聲明!

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



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