C# 异步方法的使用

?  前言

C# 中的异步方法是 C#5.0 才有的新特性,可以在执行当前方法的同时异步的去执行其他方法。

?  什么是异步方法

1)   异步方法,是指在执行当前方法的同时,去执行其他异步方法,但不会阻塞当前方法的线程。

2)   使用了 async 修饰符的方法称为异步方法,通常配合 await 运算符和 Task 异步任务一起使用。

3)   Task 分为两种:

1.   Task,表示可以执行一个异步操作,声明如下:

public class Task : IAsyncResult, IDisposable { }

2.   Task<TResult>,表示可以执行带有返回值的异步操作,声明如下:

public class Task<TResult> : Task { }

4)   异步方法的返回类型必须为 void、Task、Task<TResult> 中的其中一种。

1.   void,表示无返回值,不关心异步方法执行后的结果,一般用于仅仅执行某一项任务,但是不关心结果的场景。

2.   Task,表示异步方法将返回一个 Task 对象,该对象通常用于判断异步任务是否已经完成,可以使用 taskObj.Wait() 或者 taskObj.IsCompleted 判断。

3.   Task<TResult>,表示异步方法将返回一个 Task<TResult> 对象,该对象的 Result 属性则是异步方法的执行结果,调用该属性时将阻塞当前线程(异步方法未执行完时)。

?  总结下:void 不关心结果;Task 只关心是否运行完成;Task<TResult> 不止关心是否运行完成,还要获得运行结果。

1.   通过几个例子来看下异步方法的特征

1)   代码如下:

public void AsyncTest()

{

ConsoleExt.WriteLine("AsyncTest() 方法开始执行,线程Id为:{0}", GetCurrentThreadId());

Test1();

ConsoleExt.WriteLine("AsyncTest() 方法结束执行,线程Id为:{0}", GetCurrentThreadId());

}

public async void Test1()

{

ConsoleExt.WriteLine("Test1() 方法开始执行,线程Id为:{0}", GetCurrentThreadId());

Task task = Task.Run(() =>

{

ConsoleExt.WriteLine("Test1() 方法中的 Task 开始执行,线程Id为:{0}", GetCurrentThreadId());

ConsoleExt.WriteLine("Test1() 方法中的 Task 结束执行,线程Id为:{0}", GetCurrentThreadId());

});

ConsoleExt.WriteLine("Test1() 方法结束执行,线程Id为:{0}", GetCurrentThreadId());

}

运行以上代码:

以上代码在 Test() 方法中,重新开启了一个新的 Task 去执行另一个任务,开启后当前线程并不会等等,则继续往下执行。

2)   调用 Task 的 Wait() 方法(阻塞线程)

Task task = Task.Run(() =>

{

ConsoleExt.WriteLine("Test1() 方法中的 Task 开始执行,线程Id为:{0}", GetCurrentThreadId());

ConsoleExt.WriteLine("Test1() 方法中的 Task 结束执行,线程Id为:{0}", GetCurrentThreadId());

});

task.Wait();

运行以上代码:

可见,调用 Wait() 方法后,当前线程被阻塞了,直到 Task 执行完成后,当前线程才继续执行。

3)   修改 Test1() 方法

public async void Test1()

{

ConsoleExt.WriteLine("Test1() 方法开始执行,线程Id为:{0}", GetCurrentThreadId());

await Task.Run(() =>

{

ConsoleExt.WriteLine("Test1() 方法中的 Task 开始执行,线程Id为:{0}", GetCurrentThreadId());

ConsoleExt.WriteLine("Test1() 方法中的 Task 结束执行,线程Id为:{0}", GetCurrentThreadId());

});

ConsoleExt.WriteLine("Test1() 方法结束执行,线程Id为:{0}", GetCurrentThreadId());

}

运行以上代码:

1.   以上代码在 Test() 方法上加了 async 关键字,并且使用 await 关键字等待异步任务执行完成,当前线程并没有阻塞。

2.   注意:当前线程遇到 await 时,则立刻回到调用方法继续往下执行。而 Task 执行完成之后将执行 await 之后的代码,并且与 await 之前的线程不是同一个。

原文地址:https://www.cnblogs.com/abeam/p/8729508.html

时间: 2024-07-30 09:43:59

C# 异步方法的使用的相关文章

C#学习日志 day8 -------------- async await 异步方法入门(引用博客)以及序列化和反序列化的XML及json实现

首先是异步方法的介绍,这里引用自http://www.cnblogs.com/LoveJenny/archive/2011/11/01/2230933.html async and await 简单的入门 如果有几个Uri,需要获取这些Uri的所有内容的长度之和,你会如何做? 很简单,使用WebClient一个一个的获取uri的内容长度,进行累加. 也就是说如果有5个Uri,请求的时间分别是:1s 2s 3s 4s 5s. 那么需要的时间是:1+2+3+4+5=(6*5)/2=15. 如果采用并

BeginInvoke、ThreadPool、Task三类异步方法的区别和速度比较

  速度(最快为1) 返回值 多参数 等待在时限内完成 超时后结束 ThreadPool.UnsafeQueueUserWorkItem() 1 非原生支持1 非原生支持 非原生支持3 不支持 ThreadPool.QueueUserWorkItem() 2.7 非原生支持1 非原生支持 非原生支持3 不支持 Task() 4.5 支持2 非原生支持 支持 自愿结束 Delegate.BeinInvoke() 25.4 非原生支持1 支持 支持4 不支持 Thread.Start() 11009

折腾 async/await 调用传统 Begin/End 异步方法

最近在改进园子的图片上传程序,希望实现用户上传图片时同时将图片文件保存在三个地方:1)服务器本地硬盘:2)又拍云:3)阿里云OSS.并且在保存时使用异步操作. 对于异步保存到本地硬盘,只需用 Steam.CopyToAsync() 将上传文件流异步复制到 FileStream 即可. 对于异步保存至又拍云,只要借助 WebRequest.GetRequestStreamAsync() + Steam.CopyToAsync() 就可以实现. 而阿里云OSS提供了 .NET SDK,使用起来很方便

.net异步性能测试(包括ASP.NET MVC WebAPI异步方法)

很久没有写博客了,今年做的产品公司这两天刚刚开了发布会,稍微清闲下来,想想我们做的产品还有没有性能优化空间,于是想到了.Net的异步可以优化性能,但到底能够提升多大的比例呢?恰好有一个朋友正在做各种语言的异步性能测试(有关异步和同步的问题,请参考客<AIO与BIO接口性能对比>),于是我今天写了一个C#的测试程序. 首先,建一个 ASP.NET MVC WebAPI项目,在默认的控制器 values里面,增加两个方法: // GET api/values?sleepTime=10 [HttpG

HttpClient中异步方法的同步调用

在System.Net.Http中,提供了使用Http与远程服务器通讯的httpClient,但是里面都是异步方法,有时候我们并不需要使用异步操作.这个时候可以使用如下的方式来进行同步调用. class Program { static void Main(string[] args) { string _address = "http://api.worldbank.org/countries?format=json"; // Create an HttpClient instanc

C#多线程编程之:异步方法调用

异步方法 当一个线程调用方法后,直到方法执行完毕,线程才继续执行,这种方法被称为同步方法.然而,有些方法执行时间可能非常长,比如串口操作或访问网络,这样线程被阻塞,而无法响应用户的其他请求.这种情况通常是无法忍受的,所以这时我们应该使用异步方法. 异步方法的原理是,在方法调用前为异步方法指定一个回调函数,方法调用后被线程池中的一个线程接管,执行该方法.主线程立即返回,继续执行其他工作或响应用户请求.如果异步方法执行完毕,回调函数被自动执行,以处理异步方法的调用结果. 如何实现异步方法呢?C#通过

ICE的异步方法调用

转自:http://blog.sina.com.cn/s/blog_45497dfa0100nwbr.html http://www.cnblogs.com/mawanglin2008/articles/3411735.html ICE的AMI和AMD: AMI:指的是客户端的调用.一般有一个代理类,一个回调类. 从服务端返回的数据在回调类中的ice_response函数中. AMD:指的是服务端对客户端的调用分派.一般进行业务处理需要自己写一个类继承于_Disp类.重载method_async

[C#] 异步编程 - 剖析异步方法

剖析异步方法 序 这是上篇<开始接触 async/await 异步编程>(入门)的第二章内容,主要是深入了解异步方法,建议大家先看入门篇,很短. 本文要求了解委托的使用. 目录 介绍异步方法 异步方法:在执行完成前立即返回调用方法,在调用方法继续执行的过程中完成任务. 语法分析: (1)关键字:方法头使用 async 修饰. (2)要求:包含 N(N>0) 个 await 表达式,表示需要异步执行的任务. (3)返回类型:只能返回 3 种类型(void.Task 和 Task<T&

MSDN搬运 之 [使用 IAsyncResult 调用异步方法]

使用 IAsyncResult 调用异步方法 .NET Framework 和第三方类库中的类型可以提供允许应用程序在主应用程序线程之外的线程中执行异步操作的同时继续执行的方法.下面几部分介绍了在调用使用 IAsyncResult 设计模式的异步方法时可以采用的几种不同方式,并提供了演示这些方式的代码示例. 通过结束异步操作来阻止应用程序执行. 使用 AsyncWaitHandle 阻止应用程序的执行. 轮询异步操作的状态. 使用 AsyncCallback 委托结束异步操作. 通过结束异步操作

UWP开发:异步方法返回集合的数据绑定问题

——最近在做UWP开发,其中请求API数据的时候,往往是通过异步请求网络,再处理json数据,返回集合对象.通常,我们的做法是将集合数据在ViewModel层进行处理,让ViewModel实现ObservableCollection接口,然后在View层后台实例化ViewModel对象,前台绑定对象.这样就实现了集合的绑定和通知.这里需要注意,集合的绑定,不单单是绑定,而且要实现绑定通知,才算真正的绑定. 为什么这么说呢?看一下在开发中遇到的问题: 由于一个简单的页面,需要绑定一组集合数据,因为