一、TaskCompletionSource类的作用
TaskCompletionSource类回调代码转换为可以等待的Task,TaskCompletionSource本身不是可等待的,它也不是有效的异步方法返回类型。一旦TaskCompletionSource给了你一个任务,你可以简单地返回那个任务,就像你在异步方法中做其他任何事情一样。
二、代码示例
static void Main(string[] args) { TaskCompletionSource<bool> tcs1= new TaskCompletionSource<bool>(); Task.Run( () => ChoiceTicket(tcs1) ); Task.Run( () => PayForMoney(tcs1) ); Console.ReadKey(); } static async void PayForMoney(TaskCompletionSource<bool> tcs) { await tcs2.Task; Console.WriteLine("选购支付宝支付"); tcs.SetResult(true); Thread.Sleep(3000); Console.WriteLine("支付完成"); Console.WriteLine("跳到火车票软件完成"); } static async Task<bool> ChoiceTicket(TaskCompletionSource<bool> tcs) { Console.WriteLine("选购火车票"); Console.WriteLine("跳转到到支付页面"); tcs2.SetResult(10); await tcs.Task; Console.WriteLine("订票完成"); return tcs.Task.Result; }
简单的讲TaskCompletionSource可以实现Task异步等待的功能,await TaskCompletionSource.task会在其他线程TaskCompletionSource.setResult执行后再继续执行。
代码:
1 private string AwaitByTaskCompleteSource(Func<Task<string>> func) 2 { 3 var taskCompletionSource = new TaskCompletionSource<string>(); 4 var task1 = taskCompletionSource.Task; 5 Task.Run(async () => 6 { 7 var result = await func.Invoke(); 8 taskCompletionSource.SetResult(result); 9 }); 10 var task1Result = task1.Result; 11 Debug.WriteLine($"3. AwaitByTaskCompleteSource end:{task1Result}"); 12 return task1Result; 13 }
var task1Result = task1.Result;会暂停执行,直到taskCompletionSource.SetResult(result);赋值后才会继续执行。Task.result也会实现暂停功能,但是Task无法定义一个可以赋值的全局变量,taskCompletionSource可以不要实体Task的任务,实现暂停功能。
var tt = Task<int>.Run(() => { for (int i = 0; i < 300; i++) { Console.Write(1); } return 10; }); var t1 = tt.Result; Task.Run(() => { for (int i = 0; i < 300; i++) { Console.Write(2); } });
var t1 = tt.Result该方法也是Task的一种暂停等待功能,在需要Task.result的地方会卡死等待task执行完后再继续向下执行。该运行结果是先输出1,再输出2,如果没有Task.result代码,则是1和2交替输出。