• Task异步编程,刨根到底


    1. 编译器到底对await做了什么

    await 一个异步操作的时候,实际上编译器会创建一个状态机,这个状态机包含了调用者的上下文变量,状态机使用yield迭代器实现,状态机由clr调度,每次运行都会重新加入回队列,直到Task完成或异常结束

    2.Task有哪些实现方式

    经常我们可以看到一些库中使用TaskCompletionSource来创建Task,改变Task的状态,实际上TaskCompletionSource只是在Task基础上做简单的封装操作
    TaskCompletionSource会直接创建一个Task,设置Result也是直接在Task上设置结果,不同手动操作的地方就是做了自旋等待Task.IsCompleted再返回,保证线程安全性
    所以Task的实现就是将Task的状态切换补完的一个过程,让其成为一个Actor模型,实现方式可以自由发挥

    3.clr到底怎么调度Task

    所有的Task都是由TaskScheduler调度,最终进入到ThreadPool队列中,然后clr获取队列中的工作项并运行
    Task.Wait() 操作会先将 Task 移出 TaskScheduler 然后再使用当前线程执行

    TaskScheduler 有两种Scheduler实现,默认是ThreadPoolTaskScheduler

    Task.Run将会在内部 new Task 创建一个任务,并将Task添加到默认的TaskScheduler.Default
    TaskScheduler默认是使用ThreadPoolTaskScheduler实现

    Task.Run调用TaskScheduler.QueueTask方法将Task添加到任务队列中,在ThreadPoolTashScheduler中并没有保存任务队列,而是直接调用
    ThreadPool中的UnsafeQueueCustomWorkItem方法添加到ThreadPool中,由ThreadPool管理任务队列

    ThreadPool中有一个全局的工作队列,所有异步任务都将会加入到队列中,并由clr去获取队列中的IThreadPoolWorkItem运行

    ThreadPool根据工作队列的数量,首先会先创建CPU核心数数量的工作线程,并以每秒一个的速度创建新线程

    ThreadPool中,规定了任务的时间片,每个时间片为30个时钟,每个线程运行满一个时间片才会返回线程池
    CPU时钟使用Environment.TickCount来计算

  • 相关阅读:
    自学人工智能之数学篇,数学入门并不难
    2018-8-10-win10-uwp-使用资源在后台创建控件
    2019-9-2-win10-uwp-弹起键盘不隐藏界面元素
    2019-7-31-程序猿修养-日志应该如何写
    2018-11-19-WPF-在image控件用鼠标拖拽出矩形
    2019-8-31-C#-如何给-ValueTuple-返回值添加注释
    2019-11-12-浅谈-Windows-桌面端触摸架构演进
    2018-8-10-win10-uwp-打开文件管理器选择文件
    2018-8-10-win10-uwp-验证输入-自定义用户控件
    2019-8-31-dotnet-特性-DynamicallyInvokable-是用来做什么的
  • 原文地址:https://www.cnblogs.com/Gool/p/9550972.html
Copyright © 2020-2023  润新知