在 .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>,没找到中文版,恰巧也想提 ...
随机推荐
- hdu5558
hdu5558 题意 给出一个字符串,按照特殊规则进行加密. 假设已经加密了前 \(i\) 个字符,从第 \(i+1\) 个字符开始找到 \(S[i..N]\) 的长度为 \(K\) 的最长前缀等于 ...
- 见微知著(三):解析ctf中的pwn--Fastbin和bins的溢出
1月1号写博客,也是不容易呀!大家新年快乐呀! 先从Fastbin看起,是2015年RCTF的一道pwn题,shaxian.先看看代码的大致流程,随便输入一下: 这个题目关键之处在于堆溢出,对于堆种类 ...
- Express下使用formidable实现POST表单上传文件并保存
Express下使用formidable实现POST表单上传文件并保存 在上一篇文章中使用formidable实现了上传文件,但没将它保存下来. 一开始,我也以为是只得到了文件的相关信息,需要用fs. ...
- 【PHP】mysql基本操作整合
php版本:PHP Version 5.5.1 环境:windows10 XMAPP 数据库:mysql 代码: <?php function connetionDB($servername, ...
- 10.3(Java学习笔记)JDBC时间操作
一.时间分类 数据库 java类 Date ---- java.sql.Date 表示日期 yyyy-MM--dd (年月日) Time ----java.sql.Time 表示 ...
- 【iOS微博客户端开发】1、微博整体项目的构建
回顾自己做过的项目,总结里面的知识点,分享自己参照WXHL的视频开发的一个模拟微博客户端的过程,为了还在IOS上找不到项目参考的朋友,这里会由一系列手把手的教程,如有不足,还希望可以抖抖小手,献上您宝 ...
- 关于ComboGrid取值为非下拉框数据是,隐藏面板数据清空
$('#areaGuid').combogrid({ panelWidth: 300, idField: 'guid', textField: 'name', mode: 'remote', meth ...
- python3用pyqt5开发简易浏览器
http://python.jobbole.com/82715/ 在这篇教程中,我们会用 Python 的 PyQt 框架编写一个简单的 web 浏览器.关于 PyQt ,你可能已经有所耳闻了,它是 ...
- 【转载】网络攻击技术(三)——Denial Of Service & 哈希相关 & PHP语言 & Java语言
找到了这个系列的原始作者: http://www.cnblogs.com/rush/archive/2012/02/05/2339037.html 最近网络安全成了一个焦点,除了国内明文密码的安全事件 ...
- 测试网站页面网速的Python脚本
一.测试网站页面网速脚本 [root@salt ~]# cat check_url.py #!/usr/bin/python # coding: UTF-8 import StringIO,pycur ...