C# 8 - using声明 和 异步流

这两个主题没什么关系,可是怕文章过短被移除主页。html

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语句的话,那资源就不会被清理: async

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语句块简单一些,直接看例子: spa

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这个资源是能够被清理掉的: htm

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

能够看到db被Disposed了,可是您确定也发现了不一样之处:最后两行输出的顺序发生了变化。 对象

 

在使用using语句块的时候,清理动做发生在using块结束的时候: blog

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任务的时候,该线程是能够去作其它工做的。而当程序继续执行的时候,它确实可能结束于其它的线程。 

更详细内容请点击:官方教程

原文出处:https://www.cnblogs.com/cgzl/p/11773102.html

相关文章
相关标签/搜索