C#Task参数(TaskCreationOptions)
位于 System.Threading.Tasks.TaskContinuationOptions
Thread是基于操作系统级别的线程,而ThreadPool和Task不会创建自己的操作系统线程,二者是由任务调度器(TaskScheduler)执行,默认的调度程序仅仅在ThreadPool上运行。由于任务在ThreadPool上运行,因此创建配置不适合的Task可能会将系统默认的线程池给填满导致其他操作的线程阻塞 。
PreferFairness
提示 System.Threading.Tasks.TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。
LongRunning
指定任务将是长时间运行的、粗粒度的操作,涉及比细化的系统更少、更大的组件。 它会向 System.Threading.Tasks.TaskScheduler提示,过度订阅可能是合理的。 可以通过过度订阅创建比可用硬件线程数更多的线程。 它还将提示任务计划程序:该任务需要附加线程,以使任务不阻塞本地线程池队列中其他线程或工作项的向前推动。设置此项后,告诉任务调度器TaskScheduler启动新的线程,而不是在ThreadPool上运行。
AttachedToParent
指定将任务附加到任务层次结构中的某个父级。 默认情况下,子任务(即由外部任务创建的内部任务)将独立于其父任务执行。 可以使用AttachedToParent选项以便将父任务和子任务同步。 请注意,如果使用 DenyChildAttach选项配置父任务,则子任务中的AttachedToParent 选项不起作用,并且子任务将作为分离的子任务执行。
static void Main(string[] args)
{
Task.Factory.StartNew(() =>
{
Task.Factory.StartNew(() =>
{
Thread.Sleep(500);
Console.WriteLine("t1 end");
}, TaskCreationOptions.AttachedToParent);
Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
Console.WriteLine("t2 end");
}, TaskCreationOptions.AttachedToParent);
}).Wait();
Console.WriteLine("main end");
Console.ReadKey();
}
当t1和t2都完成后main才会完成。
DenyChildAttach
指定任何尝试作为附加的子任务执行(即,使用AttachedToParent选项创建)的子任务都无法附加到父任务,会改成作为分离的子任务执行。
static void Main(string[] args)
{
Task.Factory.StartNew(() =>
{
Task.Factory.StartNew(() =>
{
Thread.Sleep(500);
Console.WriteLine("t1 end");
}, TaskCreationOptions.AttachedToParent);
Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
Console.WriteLine("t2 end");
}, TaskCreationOptions.AttachedToParent);
}, TaskCreationOptions.DenyChildAttach).Wait();
Console.WriteLine("main end");
Console.ReadKey();
}
和上例一样,当时将main配置成 DenyChildAttach,会发现main先完成,随后t1和t2才完成。给没有子任务的Task配置该参数无效。