“What does Task.Wait do?”

Simple question, right? At a high-level, yes, the method achieves what its name implies, preventing the current thread from making forward progress past the call to Wait until the target Task has completed, one way or another. If the Task ran to completion, Wait will return successfully. If the Task completed due to faulting or being canceled, it will throw an exception indicating the relevant details (since the waiting code likely expects that all work to be completed by the task ran successfully if Wait returns successfully).

The details are a bit more interesting. Wait could simply block on some synchronization primitive until the target Task completed, and in some cases that’s exactly what it does. But blocking threads is an expensive venture, in that a thread ties up a good chunk of system resources, and a blocked thread is dead weight until it’s able to continue executing useful work. Instead, Wait prefers to execute useful work rather than blocking, and it has useful work at its finger tips: the Task being waited on. If the Task being Wait’d on has already started execution, Wait has to block. However, if it hasn’t started executing, Wait may be able to pull the target task out of the scheduler to which it was queued and execute it inline on the current thread.

To do that, Wait asks for assistance from the target scheduler, by making a call to the TaskScheduler’s TryExecuteTaskInline method. TryExecuteTaskInline can do whatever logic the scheduler needs in order to validate that the current context is acceptable for inlining the Task. If it is, the scheduler tries to execute the task then and there as part of the call to TryExecuteTaskInline (using the base TaskScheduler’s TryExecuteTask method) and returns whether the Task could be executed. If it couldn’t be executed in TryExecuteTaskInline, the scheduler returns false, and Wait will need to block until the Task completes. A Task may not be able to be executed if it’s already been or is currently being executed elsewhere. As an example of this, the default scheduler (based on the ThreadPool) is aggressive about inlining, but only if the task can be efficiently removed from the data structures that hold tasks internally in the ThreadPool (such as if the task is living in the local queue associated with the thread attempting to inline it).

This is also very similar to what happens when Task.RunSynchronously is used to execute a Task (RunSynchronously may be used instead of Task.Start to run a Task currently in the TaskStatus.Created state). RunSynchronously results in the Framework calling the target scheduler’s TryExecuteTaskInline, allowing the scheduler to decide whether to inline or not. If the scheduler chooses not to inline, the Task will instead be queued to the scheduler, and the system will block until the Task is completed.

Of course, schedulers may want to behave differently depending on whether the code is explicitly choosing to inline (e.g. RunSynchronously) or whether the inlining is happening implicitly (e.g. Wait). To support this difference, in addition to accepting as a parameter the Task to be inlined, TryExecuteTaskInline also accepts as a parameter a Boolean taskWasPreviouslyQueued. This value will be false if it is known that the specified task has not yet been submitted to the scheduler, and true otherwise. If RunSynchronously is being used, taskWasPreviouslyQueued will be false; if Wait, it will be true. The default scheduler does, in fact, differentiate between these two cases, in that it always supports explicit inlining through RunSynchronously.

原文:https://devblogs.microsoft.com/pfxteam/task-wait-and-inlining

Task.Wait and “Inlining”的更多相关文章

  1. task 限制任务数量(转自msdn)

    public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler { // Indicates whether the current ...

  2. 怎么设置task的最大线程数

    //-------------------------------------------------------------------------- // // Copyright (c) Mic ...

  3. C# Task WaitAll和WaitAny

    Task 有静态方法WaitAll和WaitAny,主要用于等待其他Task完成后做一些事情,先看看其实现部分吧: public class Task : IThreadPoolWorkItem, I ...

  4. C# Task ContinueWith的实现

    看了上一篇C# Task 是什么?返回值如何实现? Wait如何实现 我们提到FinishContinuations方法中会调用TaskContinuation实例,那么我们的ContinueWith ...

  5. Asp.Net任务Task和线程Thread

    Task是.NET4.0加入的,跟线程池ThreadPool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化都会创建一个新的线程.任务(Task)是架构在线程之上的, ...

  6. 走进Task(2):Task 的回调执行与 await

    目录 前言 Task.ContinueWith ContinueWith 的产物:ContinuationTask 额外的参数 回调的容器:TaskContinuation Task.Continue ...

  7. Concepts:Request 和 Task

    当SQL Server Engine 接收到Session发出的Request时,SQL Server OS将Request和Task绑定,并为Task分配一个Workder.在TSQL Query执 ...

  8. .Net多线程编程—任务Task

    1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 object AsyncState 表示在 ...

  9. nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...

随机推荐

  1. Python __new__ 实现单例模式 python经典面试题

    话不多说,上代码 class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance' ...

  2. Jexus~Linux环境下的部署

    Jexus 即 Jexus Web Server,简称JWS,是Linux平台上的一款ASP.NET WEB服务器,是 Linux.Unix.FreeBSD 等非Windows系统架设 ASP.NET ...

  3. 从0打卡leetcode之day 5 ---两个排序数组的中位数

    前言 我靠,才坚持了四天,就差点不想坚持了.不行啊,我得把leetcode上的题给刷完,不然怕是不好进入bat的大门. 题目描述 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . ...

  4. C#2.0导航

    主要特性 泛型 类型和方法的参数化 可空类型 值类型可为null 委托 更简化的方式 迭代器 简单的foreach,不简单的状态机

  5. HDFS架构及原理

    原文链接:HDFS架构及原理 引言 进入大数据时代,数据集的大小已经超过一台独立物理计算机的存储能力,我们需要对数据进行分区(partition)并存储到若干台单独的计算机上,也就出现了管理网络中跨多 ...

  6. Python并发编程之消息队列补充及如何创建线程池(六)

    大家好,并发编程 进入第六篇. 在第四章,讲消息通信时,我们学到了Queue消息队列的一些基本使用.昨天我在准备如何创建线程池这一章节的时候,发现对Queue消息队列的讲解有一些遗漏的知识点,而这些知 ...

  7. (摘)sql-索引的作用(超详细)

    (一)深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonc ...

  8. python-操作文件和目录

    操作文件和目录 为文件和目的操作经常用到os模块和shutil模块. 常用方法: 获取当前脚本工作的目录路径:os.getcwd(),返回的是str类型. 返回指定目录下的所有文件和目录名:os.li ...

  9. Java开发笔记(八十)利用反射技术操作私有方法

    前面介绍了如何利用反射技术读写私有属性,不单是私有属性,就连私有方法也能通过反射技术来调用.为了演示反射的逆天功能,首先给Chicken鸡类增加下列几个私有方法,简单起见弄来了set***/get** ...

  10. Java基础:HashMap中putAll方法的疑惑

    最近回顾了下HashMap的源码(JDK1.7),当读到putAll方法时,发现了之前写的TODO标记,当时由于时间匆忙没来得及深究,现在回顾到了就再仔细思考了下 @Override public v ...