在 .NET 4.0 下编写扩展代码以支持 async 异步编程
微软在C# 5中引入了async、await这两个异步编程的关键字,要使用这两个关键字需要你的IDE支持C#5.0语法,也就意味着你需要使用VS 2012版本以上IDE,或者在Vs2010卸载其编译器在重新安装,这并不是本文的重点,有需求的朋友点击这篇博客,现在都快接近2019年,VS2019 预览版都出来了,现在使用Vs2010确实有点更不上时代了,建议大家升级一下vs,其他问题可以自行百度谷歌解决下。
async和await带给我们的方便是巨大的,从代码的简洁或者处理UI阻塞问题,都是很便捷的,而XP系统最高只支持.Net 4.0,也就意味着,假如你编写的Winform程序使用了这两个关键字将不能在XP中,而目前很多系统仍然使用着XP,因此很有必要在.Net 4 环境下使用 async异步编程。
当我们创建一个.Net Framework 4.0的项目时候,在使用async 和 await的时候,代码如下:
static void Main(string[] args)
{
Console.WriteLine("异步方法调用前:" + Thread.CurrentThread.ManagedThreadId.ToString());
Test();
Console.WriteLine("异步方法调用后:" + Thread.CurrentThread.ManagedThreadId.ToString());
Console.Read();
} public async static void Test()
{
Console.WriteLine("异步方法等待前:" + Thread.CurrentThread.ManagedThreadId.ToString());
Console.WriteLine("开始等待:" + DateTime.Now.ToString());
await Wait();
Console.WriteLine("异步方法等待后:" + Thread.CurrentThread.ManagedThreadId.ToString());
Console.WriteLine("结束等待:" + DateTime.Now.ToString());
} public static Task Wait()
{
Action action = () =>
{
Console.WriteLine("任务运行:" + Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep();
Console.WriteLine("任务运行后:" + Thread.CurrentThread.ManagedThreadId.ToString());
};
Task task = null;
// task= TaskEx.Run(action);
task = new Task(action);
task.Start();
return task;
}
这时候编译器会报一个错误 :CS1061 “Task”未包含“GetAwaiter”的定义,并且找不到可接受第一个“Task”类型参数的可访问扩展方法“GetAwaiter”(是否缺少 using 指令或程序集引用?)
而在.Net 4.5下,是不会报这样错的。在异步的环境下,正确执行的情况下,Test()方法会单独开辟一个线程,所以整个测试,会在Main方法中Test()方法是异步的,具体执行顺序如下:
回归到.Net 4.0中报的错:“Task”未包含“GetAwaiter”的定义,并且找不到可接受第一个“Task”类型参数的可访问扩展方法“GetAwaiter”。由此我们推断.Net 4.5 跟 .Net 4.0在处理异步的区别是否在于多了Task的扩展方法GetAwaiter()。
-------------------------------------------------------------------------------------华丽的过度线-------------------------------------------------------------------------------------------------------------------------
由于涉及到 .net async 状态机,这东西目前不是目前我一下两下可以懂的,先将实现贴出来,以后学得深了在完善此随笔。
新建一个类TaskEx,用如下的代码替换掉类里面的所有内容,会发现.Net 4.0下的报错会消失,也可以正常的使用异步async。有兴趣的同学可以在Github项目参考牛人写的代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks; namespace System.Threading.Tasks
{
internal static class TaskEx
{
public static TaskAwaiter GetAwaiter(this Task task)
{
return new TaskAwaiter(task);
} public static TaskAwaiter<T> GetAwaiter<T>(this Task<T> task)
{
return new TaskAwaiter<T>(task);
}
public static Task Run(Action action)
{
return Task.Factory.StartNew(action);
}
}
internal struct TaskAwaiter : INotifyCompletion
{
readonly Task task;
internal TaskAwaiter(Task task)
{
this.task = task;
} internal static TaskScheduler TaskScheduler
{
get
{
if (SynchronizationContext.Current == null)
return TaskScheduler.Default;
else
return TaskScheduler.FromCurrentSynchronizationContext();
}
} public bool IsCompleted
{
get { return task.IsCompleted; }
} public void OnCompleted(Action continuation)
{
this.task.ContinueWith(
delegate (Task task) { //Console.WriteLine("状态机回调函数信息:"+Thread.CurrentThread.ManagedThreadId);
//Console.WriteLine("\t名称:"+continuation.Method.Name);
//Console.WriteLine("\t所属类型:" + continuation.Method.DeclaringType.ToString());
continuation();
}, TaskAwaiter.TaskScheduler);
} public void GetResult()
{
try
{
task.Wait();
}
catch (AggregateException ex)
{
throw ex.InnerExceptions[];
}
}
} internal struct TaskAwaiter<T> : INotifyCompletion
{
readonly Task<T> task; internal TaskAwaiter(Task<T> task)
{
this.task = task;
} public bool IsCompleted
{
get { return task.IsCompleted; }
} public void OnCompleted(Action continuation)
{
this.task.ContinueWith(
delegate (Task<T> task) {
continuation();
}, TaskAwaiter.TaskScheduler);
} public T GetResult()
{
try
{
return task.Result;
}
catch (AggregateException ex)
{
throw ex.InnerExceptions[];
}
}
}
} namespace System.Runtime.CompilerServices
{
internal interface INotifyCompletion
{
void OnCompleted(Action continuation);
} internal interface ICriticalNotifyCompletion : INotifyCompletion
{
[SecurityCritical]
void UnsafeOnCompleted(Action continuation);
} internal interface IAsyncStateMachine
{
void MoveNext();
void SetStateMachine(IAsyncStateMachine stateMachine);
} internal struct AsyncVoidMethodBuilder
{
public static AsyncVoidMethodBuilder Create()
{
return new AsyncVoidMethodBuilder();
} public void SetException(Exception exception)
{
throw exception;
} public void SetResult()
{
} public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// Should not get called as we don't implement the optimization that this method is used for.
throw new NotImplementedException();
} public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
} public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine
{
awaiter.OnCompleted(stateMachine.MoveNext);
} public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine
{
awaiter.OnCompleted(stateMachine.MoveNext);
}
} internal struct AsyncTaskMethodBuilder
{
TaskCompletionSource<object> tcs; public Task Task { get { return tcs.Task; } } public static AsyncTaskMethodBuilder Create()
{
AsyncTaskMethodBuilder b;
b.tcs = new TaskCompletionSource<object>();
return b;
} public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
} public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// Should not get called as we don't implement the optimization that this method is used for.
throw new NotImplementedException();
} public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine
{
awaiter.OnCompleted(stateMachine.MoveNext);
} public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine
{
awaiter.OnCompleted(stateMachine.MoveNext);
} public void SetResult()
{
tcs.SetResult(null);
} public void SetException(Exception exception)
{
tcs.SetException(exception);
}
} internal struct AsyncTaskMethodBuilder<T>
{
TaskCompletionSource<T> tcs; public Task<T> Task { get { return tcs.Task; } } public static AsyncTaskMethodBuilder<T> Create()
{
AsyncTaskMethodBuilder<T> b;
b.tcs = new TaskCompletionSource<T>();
return b;
} public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
} public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// Should not get called as we don't implement the optimization that this method is used for.
throw new NotImplementedException();
} public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine
{
awaiter.OnCompleted(stateMachine.MoveNext);
} public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine
{
AwaitOnCompleted(ref awaiter, ref stateMachine);
} public void SetResult(T result)
{
tcs.SetResult(result);
} public void SetException(Exception exception)
{
tcs.SetException(exception);
}
}
}
在 .NET 4.0 下编写扩展代码以支持 async 异步编程的更多相关文章
- 【eclipse jar包】在编写java代码时,为方便编程,常常会引用别人已经实现的方法,通常会封装成jar包,我们在编写时,只需引入到Eclipse中即可。
Eclipse中导入外部jar包 在编写java代码时,为方便编程,常常会引用别人已经实现的方法,通常会封装成jar包,我们在编写时,只需引入到Eclipse中即可. 工具/原料 Eclipse 需要 ...
- 怎样实如今Windows下编写的代码,直接在Linux下编译
方法一: 怎样实如今Windows7下编写Linux程序.写完程序以后.不用复制文件,直接在Linux(RHEL6.5)机器上编译最新的代码. 1.首先将Windows的代码目录设置为共享目录: 2. ...
- 如何在.net 4.0下安装TLS1.2的支持
原始出处:www.cnblogs.com/Charltsing/p/Net4TLS12.html 作者QQ: 564955427 最近提交请求发生错误:不支持请求的协议,研究了一下TLS1.2,发现这 ...
- 转 linux下php扩展mysqli的支持
前两天一个站点转移过来,因为给我的数据库有问题,我也没有仔细处理这个站点.今天把数据库弄好了,发现还是用不了,报的错误如下:Fatal error: Class ‘mysqli’ not found ...
- 在 C# 中使用 Span<T> 和 Memory<T> 编写高性能代码
目录 在 C# 中使用 Span 和 Memory 编写高性能代码 .NET 中支持的内存类型 .NET Core 2.1 中新增的类型 访问连续内存: Span 和 Memory Span 介绍 C ...
- 解决VS2012编写JQuery代码不能智能提示的问题(其他js库的代码提示设置估计类似)
VS默认设置下编写jQuery代码是这样的: 解决办法: 1.在项目的"管理NuGet程序包"中安装JQuery: 2.打开:工具 -> 选项 -> 文本编辑器 -&g ...
- .NET4.0下使用Net2.0类库或程序集
最近在项目上一直使用.net4.0 framework,使用ffmepeg下的一个dll时,提示只能在2.0下运行,解决方法如下: app.config中添加一个配置节:startup <?xm ...
- C#与C++的发展历程第三 - C#5.0异步编程巅峰
系列文章目录 1. C#与C++的发展历程第一 - 由C#3.0起 2. C#与C++的发展历程第二 - C#4.0再接再厉 3. C#与C++的发展历程第三 - C#5.0异步编程的巅峰 C#5.0 ...
- 异步编程系列第04章 编写Async方法
p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...
随机推荐
- UVALive 5097 Cross the Wall
贪心思想,$dp$,斜率优化. 首先将人按照$w$从大到小排序,如果$w$一样,按$h$从大到小排.这样一来,某位置之后,比该位置$h$小的都是不需要考虑的. 因此,形成了如下图所示的结果: 即第一个 ...
- 优先队列priority_queue
优先队列容器与队列一样,只能从队尾插入元素,从队首删除元素.但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队.这点类似于给队列 ...
- struts2中css,js等资源无效 非路径问题(新手问题)
一个小小的Strust2例子 然后发现css,js,图片用不了,debugger下发现无法访问这些资源(404错误),妈的,那个例子明明可以的,起码从书上的图片看. 发现是web.xml中的过滤器的问 ...
- 【单调队列】bzoj2096 [Poi2010]Pilots
用两个单调队列维护序列中的最大值和最小值即可. poi~ #include<cstdio> #include<algorithm> using namespace std; i ...
- [CF911B]Two Cakes
题目大意: 有两种蛋糕,分别被切成了a块和b块,要把这些蛋糕分到n个盘子里. 要求每个盘子里只能有一种蛋糕,每一种蛋糕都被分.问最优情况下,盘子里至少能放几个蛋糕. 思路: 二分答案. 由于每个蛋糕都 ...
- JavaScript:this是什么
JavaScript:this是什么? 定义:this是包含它的函数作为方法被调用时所属的对象. 说明:这句话有点咬嘴,但一个多余的字也没有,定义非常准确,我们可以分3部分来理解它! 1.包含它的函数 ...
- 修改input type=file 标签默认样式的简单方法
<html><head><title></title></head><body><form id="upload ...
- 使用Spring Boot上传文件
原文:http://www.cnblogs.com/ityouknow/p/8298344.html 上传文件是互联网中常常应用的场景之一,最典型的情况就是上传头像等,今天就带着带着大家做一个Spri ...
- Solr学习、安装与Quick Start
之前用Lucene进行了一些简单的例子,现在安装Solr学习一下. 在mac下,貌似可以直接brew install solr来进行安装.尝试一下. 貌似安装成功了: ==> Summary
- linux 关闭端口
第一步查看那些程序在使用该端口 netstat -anp或者netstat -tulnp 第二步杀死进程 kill -9 xxx,杀死某个进程 killall 进程名