执行随后暂停,OnCompleted完成后重新回到状态机;
有兴趣的可以访问Github具体规范说明:https://github.com/dotnet/csharplang/blob/master/spec/expressions.md
正常Task.Delay()是基于线程池计时器的,可以用如下“骚操作”,来实现一个单线程的TaskEx.Delay():
static Action Tick = null;
void Main()
{
Start();
while (true)
{
if (Tick != null) Tick();
Thread.Sleep(1);
}
}
async void Start()
{
Console.WriteLine("执行开始");
for (int i = 1; i <= 4; ++i)
{
Console.WriteLine($"第{i}次,时间:{DateTime.Now.ToString("HH:mm:ss")} - 线程号:{Thread.CurrentThread.ManagedThreadId}");
await TaskEx.Delay(1000);
}
Console.WriteLine("执行完成");
}
class TaskEx
{
public static MyDelay Delay(int ms) => new MyDelay(ms);
}
class MyDelay : INotifyCompletion
{
private readonly double _start;
private readonly int _ms;
public MyDelay(int ms)
{
_start = Util.ElapsedTime.TotalMilliseconds;
_ms = ms;
}
internal MyDelay GetAwaiter() => this;
public void OnCompleted(Action continuation)
{
Tick += Check;
void Check()
{
if (Util.ElapsedTime.TotalMilliseconds - _start > _ms)
{
continuation();
Tick -= Check;
}
}
}
public void GetResult() {}
public bool IsCompleted => false;
}
运行效果如下:
执行开始
第1次,时间:17:38:03 - 线程号:1
第2次,时间:17:38:04 - 线程号:1
第3次,时间:17:38:05 - 线程号:1
第4次,时间:17:38:06 - 线程号:1
执行完成
注意不需要非得使用TaskCompletionSource<T>才能创建定定义的async/await。
3. 表达式树,与Expression<T>类型
是“黑魔法”,没有“操作空间”,只有当类型是Expression<T>时,才会创建为表达式树。
表达式树是C# 3.0随着LINQ一起发布,是有远见的“黑魔法”。
如以下代码:
Expression<Func<int>> g3 = () => 3;
会被编译器翻译为:
Expression<Func<int>> g3 = Expression.Lambda<Func<int>>( Expression.Constant(3, typeof(int)), Array.Empty<ParameterExpression>());
4. 插值字符串,与FormattableString类型
是“黑魔法”,没有“操作空间”。
插值字符串发布于C# 6.0,在此之前许多语言都提供了类似的功能。
只有当类型是FormattableString,才会产生不一样的编译结果,如以下代码:
FormattableString x1 = $"Hello {42}";
string x2 = $"Hello {42}";
编译器生成结果如下:
FormattableString x1 = FormattableStringFactory.Create("Hello {0}", 42);
string x2 = string.Format("Hello {0}", 42);










