C# 应用 - 多线程 3) Task.Factory

1. 与 Task.Run() 的区别;

先看一下源码:

public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable
{
public static Task Run(Action action)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return InternalStartNew(null, action, null,
default(CancellationToken),
TaskScheduler.Default,
TaskCreationOptions.DenyChildAttach,
InternalTaskOptions.None,
ref stackMark);
} internal static Task InternalStartNew(Task creatingTask, Delegate action, object state,
CancellationToken cancellationToken,
TaskScheduler scheduler,
TaskCreationOptions options,
InternalTaskOptions internalOptions,
ref StackCrawlMark stackMark)
{
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
Task task = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
task.PossiblyCaptureContext(ref stackMark);
task.ScheduleAndStart(needsProtection: false);
return task;
}
...
} public class TaskFactory
{
public Task StartNew(Action action)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task internalCurrent = Task.InternalCurrent;
return Task.InternalStartNew(internalCurrent, action, null,
m_defaultCancellationToken,
GetDefaultScheduler(internalCurrent),
m_defaultCreationOptions,
InternalTaskOptions.None,
ref stackMark);
} public Task StartNew(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task.InternalStartNew(Task.InternalCurrentIfAttached(creationOptions), action, null,
cancellationToken,
scheduler,
creationOptions,
InternalTaskOptions.None,
ref stackMark);
}
...
}

Task.Run() 是 .Net Framework 4.5 之后提出的,Task.Factory.StartNew() 可以使用更多的参数,可以认为 Task.Run 是简化版的使用,而 Task.Factory.StartNew() 主要用于需要指定该线程是长期占用的,否则用 task.Run

Task.Factory.StartNew(()=>{
...
}, TaskCreationOptions.LongRunning
); TaskCreationOptions.LongRunning 它会向 System.Threading.Tasks.TaskScheduler提示,
过度订阅可能是合理的。
可以通过过度订阅创建比可用硬件线程数更多的线程。
它还将提示任务计划程序:该任务需要附加线程,以使任务不阻塞本地线程池队列中其他线程或工作项的向前推动。

2. CancellationToken 入参:取消令牌;

可参考 https://www.cnblogs.com/MichaelLoveSna/p/14507488.html

3. TaskCreationOptions 入参:父子之间的依附态度等;

TaskCreationOptions.LongRunning;
TaskCreationOptions.AttachedToParent;
TaskCreationOptions.DenyChildAttach; TaskCreationOptions.AttachedToParent 表示该 Task 可以依附在父 Task 上,
当父 Task wait 的时候,会等待该 Task 执行完毕;
TaskCreationOptions.DenyChildAttach 就是为了避免子 Task 设置 TaskCreationOptions.AttachedToParent,
强行拒绝依附。
这一对有点像,儿子:爸,等我;父亲说:别闹,我没有你这个儿子。

4. TaskScheduler :线程调度

TaskScheduler.Default 线程池的线程
TaskScheduler.FromCurrentSynchronizationContext() 用了运行在一个与当前函数相同的线程中(也就是UI线程中,除非是 Task 的 Task)
这个描述可能听起来有点抽象,需要意会一下。
上一篇:Linux 安装gcc、gcc-c++编译器


下一篇:php推送