微軟在C# 5中引入了async、await這兩個異步編程的關鍵字,要使用這兩個關鍵字須要你的IDE支持C#5.0語法,也就意味着你須要使用VS 2012版本以上IDE,或者在Vs2010卸載其編譯器在從新安裝,這並非本文的重點,有需求的朋友點擊這篇博客,如今都快接近2019年,VS2019 預覽版都出來了,如今使用Vs2010確實有點更不上時代了,建議你們升級一下vs,其餘問題能夠自行百度谷歌解決下。html
async和await帶給咱們的方即是巨大的,從代碼的簡潔或者處理UI阻塞問題,都是很便捷的,而XP系統最高只支持.Net 4.0,也就意味着,假如你編寫的Winform程序使用了這兩個關鍵字將不能在XP中,而目前不少系統仍然使用着XP,所以頗有必要在.Net 4 環境下使用 async異步編程。git
當咱們建立一個.Net Framework 4.0的項目時候,在使用async 和 await的時候,代碼以下:github
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(2000); 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()。async
-------------------------------------------------------------------------------------華麗的過分線-------------------------------------------------------------------------------------------------------------------------異步編程
因爲涉及到 .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[0]; } } } 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[0]; } } } } 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); } } }