type
status
date
slug
summary
tags
category
icon
password
Property
Aug 9, 2024 11:59 AM

TaskCompletionSource简介

Task.Run 创建Task
另一种方式就是用TaskCompletionSource创建Task
TaskCompletionSource让你在稍后开始和结束的任意操作中创建Task
它会为你提供一个可手动执行的“从属”Task
指示操作何时结束或发生故障
他对IOBound类工作比较理想
  • 可以获得Task 的所有好处(传播值,异常,Continuation等)
  • 不需要在操作的时候阻塞线程

使用TaskCompletionSource

notion image
初始化一个实例即可
他有一个Task属性可以返回一个Task
该Task完全与TaskCompletionSource对象控制
调用图中的任意一个方法都会给Task发信号
完成、故障、取消
这些方法只能调用一次,如果再次调用:
  • setXXX会抛出异常
  • tryXXX会返回False
例子:
namespace ConsoleApp4 { internal class Program { static void Main(string[] args) { var tsc =new TaskCompletionSource<int>(); new Thread(() => { Thread.Sleep(5000); tsc.SetResult(42); }) { IsBackground=true }.Start(); Task<int> task = tsc.Task; Console.WriteLine(task.Result); } } }
namespace ConsoleApp4 { internal class Program { static void Main(string[] args) { Task<int> task = Run(() => { Thread.Sleep(5000); return 42; }); Console.WriteLine(task.Result); } static Task<TResult> Run<TResult>(Func<TResult> function) { var tcs = new TaskCompletionSource<TResult>(); new Thread(() => { try { tcs.SetResult(function()); } catch (Exception ex) { tcs.SetException(ex); } }).Start(); return tcs.Task; } } }
调用此方法相当于调用Task.Factory.StsrtNew,并使用TaskCreationOptions.LongRunning来创建非线程池的线程。

TaskCompletionSource的真正魔力

它创建Task,但是并不占用线程
GetAnswerToLife例子
namespace ConsoleApp4 { internal class Program { static void Main(string[] args) { var awaiter = GetAnswerToLife().GetAwaiter(); awaiter.OnCompleted(() => { Console.WriteLine(awaiter.GetResult()); }); Console.ReadKey(); } 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; } } }
Delay 例子
namespace ConsoleApp4 { internal class Program { static void Main(string[] args) { Delay(5000).GetAwaiter().OnCompleted(() => Console.WriteLine(42)); // 5s后,Continuation开始的时候,才占用线程 Console.ReadKey(); } static 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

例子master
Task.Delay相当于异步版本的Thread.Sleep
namespace ConsoleApp4 { internal class Program { static void Main(string[] args) { Delay(5000).GetAwaiter().OnCompleted(() => Console.WriteLine(42)); Task.Delay(5000).GetAwaiter().OnCompleted(() => Console.WriteLine(43)); Task.Delay(5000).ContinueWith(ant => Console.WriteLine(44)); // 5s后,Continuation开始的时候,才占用线程 Console.ReadKey(); } static 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; } } }
C#异步编程-21 异步中的同步上下文C#异步编程-18 异步和 continuation 以及语言的支持
Loading...
Kitety
Kitety
独特为佳,Kitety的个人博客
公告
我曾经七次鄙视自己的灵魂
--卡里·纪伯伦
第一次,当它本可进取时,却故作谦卑;
第二次,当它在空虚时,用爱欲来填充;
第三次,在困难和容易之间,它选择了容易;
第四次,它犯了错,却借由别人也会犯错来宽慰自己;
第五次,它自由软弱,却把它认为是生命的坚韧;
第六次,当它鄙夷一张丑恶的嘴脸时,却不知那正是自己面具中的一副;
第七次,它侧身于生活的污泥中,虽不甘心,却又畏首畏尾。
 
支持在线微信赞赏扶贫
notion image
 
最新评论
Loading...