一、基础知识
1、异步编程
(1)同步方法:一个应用程序调用某个方法,等到其执行完成后才进行下一步操作。
(2)异步方法:一个程序调用某个方法,在处理完成前就返回该方法。
同步和异步主要用于修饰方法。当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法;当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务,调用者不用等待该方法执行完毕,我们称这个方法为异步方法。
net4.0在ThreadPool的基础上推出了Task类,微软极力推荐使用Task来执行异步任务。
net5.0推出了async/await,让异步编程更为方便。
异步的优点:
异步的好处在于非阻塞(调用线程的不会暂停执行去等待子线程完成),因此我们把一些不需要立即使用结果、较耗时的任务设为异步执行,可以提高程序的运行效率。
2、C#异步编程的三种模式
(1)基于任务的异步模式(TAP),它使用一个方法来表示异步操作的启动和完成。
(2)基于事件的异步模式(EAP),它是用于提供异步行为的基于事件的遗留模型。它需要一个具有Async
后缀和一个或多个事件、事件处理程序委托类型和EventArg
衍生类型。
(3)异步编程模型(APM)模式(也称为IAsyncResult(模式),它是使用IAsyncResult接口提供异步行为。
3、任务和线程的区别
(1)Thread
用于开启一条单独的线程。
(2)Task
Task跟线程池Threadpool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化后都会创建一个新的线程。
Task是在ThreadPool的基础上推出的,ThreadPool中有若干数量的线程,如果有任务需要处理时,会从线程池中获取一个空闲的线程来执行任务,任务执行完毕后线程不会销毁,而是被线程池回收以供后续任务使用。当线程池中所有的线程都在忙碌时,又有新任务要处理时,线程池才会新建一个线程来处理该任务,如果线程数量达到设置的最大值,任务会排队,等待其他任务释放线程后再执行。线程池能减少线程的创建,节省开销。
ThreadPool不能控制线程的执行顺序,我们也不能获取线程池内线程取消/异常/完成的通知,即我们不能有效监控和控制线程池中的线程。
4、Task使用方法
(1)创建一个Task对象,并通过委托的方式运行某个方法
Task task=new Task(dowork);//创建Task对象,并运行方法
private void dowork()
{
//.....
}
(2)允许向委托运行的方法传递数据
Action
(3)使用Task类提供的静态方法创建和运行任务
Task task=Task.Run(()=>doWork());//创建Task对象,并运行方法
private void dowork()
{
//.....
}
二、简单异步编程
1、async和await
C#使用关键字async和await实现异步方法,async指出方法可能要异步执行操作,而await指定异步操作的地点。
(1)async
用async修饰一个方法,表明这个方法时异步的,该方法的返回类型有void、Task和Task
(2)async和await结构的执行顺序
第一步:调用方法,调用一个异步方法,然后在异步方法执行器任务的时候继续顺序执行其他语句。
第二步:执行异步方法,异步方法执行里面的工作,然后立刻返回到调用方法。
第三步:执行await,用于异步方法内部,指出异步执行的任务,一个异步方法可能包含多个await表达式。
2、应用举例
private async void btnClick_Click(object sender, EventArgs e)
{
long length = await AccessWebAsync();
// 这里可以做一些不依赖回复的操作
OtherWork();
this.richTextBox1.Text += String.Format("\n 回复的字节长度为: {0}.\r\n", length);
txbMainThreadID.Text = Thread.CurrentThread.ManagedThreadId.ToString();
}
// 使用C# 5.0中提供的async 和await关键字来定义异步方法
// 从代码中可以看出C#5.0 中定义异步方法就像定义同步方法一样简单。
// 使用async 和await定义异步方法不会创建新线程,
// 它运行在现有线程上执行多个任务.
// 此时不知道大家有没有一个疑问的?在现有线程上(即UI线程上)运行一个耗时的操作时,
// 为什么不会堵塞UI线程的呢?
// 这个问题的答案就是 当编译器看到await关键字时,线程会
private async Task AccessWebAsync()
{
MemoryStream content = new MemoryStream();
// 对MSDN发起一个Web请求
HttpWebRequest webRequest = WebRequest.Create("http://msdn.microsoft.com/zh-cn/") as HttpWebRequest;
if (webRequest != null)
{
// 返回回复结果
using (WebResponse response = await webRequest.GetResponseAsync())
{
using (Stream responseStream = response.GetResponseStream())
{
await responseStream.CopyToAsync(content);
}
}
}
txbAsynMethodID.Text = Thread.CurrentThread.ManagedThreadId.ToString() ;
return content.Length;
}
private void OtherWork()
{
this.richTextBox1.Text += "\r\n等待服务器回复中.................\n";
}
参考文献:
【1】https://blog.csdn.net/u013477973/article/details/71081836
【2】https://www.cnblogs.com/wyy1234/p/9172467.html