- Task.Run创建Task
- 另一种方式就是用TaskCompletionSource来创建Task
- TaskCompletionSource让你稍后开始和结束的任意操作中创建Task
- 它会为你提供一个可手动执行的“从属”Task
- 指示操作何时结束或发生故障
- 它会为你提供一个可手动执行的“从属”Task
- 它对IO-Bound类工作比较理想
- 可以获得所有Task的好处(传播值、异常、Continuation等)
- 不需要再操作的时候阻塞线程
使用TaskCompletionSource
- 初始化一个实例即可
- 它有一个Task属性可返回一个Task
- 该Task完全由TaskCompletionSource对象控制

- 调用任意一个方法都会给Task发信号:
- 完成、故障、取消
这些方法只能调用一次,如果再次调用:
- SetXxx会抛出异常
TryXxx会返回false
class Program{static void Main(string[] args){var tcs = new TaskCompletionSource<int>();new Thread(() =>{Thread.Sleep(5000);tcs.SetResult(42);}){IsBackground = true}.Start();// 这行代码开始执行Task<int> task = tcs.Task;Console.WriteLine(task.Result);Console.ReadLine();}}
自己实现类似于Task.Run方法
class Program{static void Main(string[] args){Task<int> task = Run(() =>{Thread.Sleep(5000);return 42;});Console.WriteLine(task.Result);}// 调用此方法相当于调用 Task.Factory.StartNew,// 并使用 TaskCreationOptions.LongRunning 选项来创建非线程池的线程static Task<TResult> Run<TResult>(Func<TResult> function){var tcs = new TaskCompletionSource<TResult>();new Thread(() =>{try{tcs.SetResult(function());}catch (Exception e){tcs.SetException(e);}}).Start();return tcs.Task;}}
TaskCompletionSource的真正魔力
它创建Task,但并不占用线程
public class Timer{static void Main(string[] args){var awaiter = GetAnswerToLife().GetAwaiter();awaiter.OnCompleted(() =>{Console.WriteLine(awaiter.GetResult());});Console.ReadLine();}static Task<int> GetAnswerToLife(){var tcs = new TaskCompletionSource<int>();var timer = new System.Timers.Timer(5000) { AutoReset = false };timer.Elapsed += delegate{timer.Dispose();tcs.SetResult(42);};timer.Start();return tcs.Task;}}
static void Main(string[] args){Delay(5000).GetAwaiter().OnCompleted(() => Console.WriteLine(42));// 5秒钟之后,Continuation 开始的时候,才占用线程}// 注意:没有非泛型版本的 TaskCompletionSourcestatic Task Delay(int milliseconds){var tcs = new TaskCompletionSource<object>();var timer = new System.Timers.Timer(milliseconds) {AutoReset = false};timer.Elapsed += delegate{timer.Dispose();tcs.SetResult(null);};timer.Start();return tcs.Task;}}
Task.Delay相当于异步版本的Task.Sleep
