使用 TaskFactory() 与 TaskFactory(CancellationToken)
Using TaskFactory() vs TaskFactory(CancellationToken)
当使用 TaskFactory(默认构造函数)并且您希望您的任务可取消时,您可以执行典型的操作:
Task.Factory.StartNew(() => DoSomeWork(token), token);
// or the equivilant
var factory = new TaskFactory();
factory.StartNew(() => DoSomeWork(token), token);
根据 MSDN,如果您使用 TaskFactory(CancellationToken)
而不是 TaskFactory()
,则:
The CancellationToken that will be assigned to tasks created by this
TaskFactory unless another CancellationToken is explicitly specified
while calling the factory methods.
这让我相信我可以做到:
TaskFactory factory = new TaskFactory(token);
factory.StartNew(() => DoSomeWork(token)); // don't need to pass token to StartNew()
... // imagine a few more tasks created just like above
// now create a special task that marches to its own drummer (token)
factory.StartNew(() => DoSomeWork(differentToken), differentToken);
当然,我为什么要那样做?将 Task.Factory.StartNew() 用于一次性任务似乎更有意义(除非我有其他常见配置)。但我离题了。所以这就是我 的想法,除了我在网上看到一些基本上看起来像这样的例子:
TaskFactory factory = new TaskFactory(token);
factory.StartNew(() => DoSomeWork(token), token);
将相同的令牌传递给 StartNew(),因为据称工厂被配置为自动与该工厂创建的任务相关联。所以我不确定我是否只是看到了正在做他们不需要做的工作的例子,或者我是否在这里误解了一些基本的东西。毕竟,如果我要显式地将令牌传递给 StartNew(),那么将它传递给 TaskFactory 构造函数的意义何在?
这是 TaskFactory
的 source:
构造函数:
public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
CheckMultiTaskContinuationOptions(continuationOptions);
CheckCreationOptions(creationOptions);
m_defaultCancellationToken = cancellationToken;
m_defaultScheduler = scheduler;
m_defaultCreationOptions = creationOptions;
m_defaultContinuationOptions = continuationOptions;
}
这是一个没有 CancellationToken
参数的重载及其实现方式:
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<TResult> function)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
}
如您所见,当您不使用带有 CancellationToken
参数的构造函数时,会使用构造函数中的 m_defaultCancellationToken
。
因此,仅当您使用没有 CancellationToken
重载的 TaskFactory.StartNew
时,在构造函数中传递 CancellationToken
才有用
当使用 TaskFactory(默认构造函数)并且您希望您的任务可取消时,您可以执行典型的操作:
Task.Factory.StartNew(() => DoSomeWork(token), token);
// or the equivilant
var factory = new TaskFactory();
factory.StartNew(() => DoSomeWork(token), token);
根据 MSDN,如果您使用 TaskFactory(CancellationToken)
而不是 TaskFactory()
,则:
The CancellationToken that will be assigned to tasks created by this TaskFactory unless another CancellationToken is explicitly specified while calling the factory methods.
这让我相信我可以做到:
TaskFactory factory = new TaskFactory(token);
factory.StartNew(() => DoSomeWork(token)); // don't need to pass token to StartNew()
... // imagine a few more tasks created just like above
// now create a special task that marches to its own drummer (token)
factory.StartNew(() => DoSomeWork(differentToken), differentToken);
当然,我为什么要那样做?将 Task.Factory.StartNew() 用于一次性任务似乎更有意义(除非我有其他常见配置)。但我离题了。所以这就是我 的想法,除了我在网上看到一些基本上看起来像这样的例子:
TaskFactory factory = new TaskFactory(token);
factory.StartNew(() => DoSomeWork(token), token);
将相同的令牌传递给 StartNew(),因为据称工厂被配置为自动与该工厂创建的任务相关联。所以我不确定我是否只是看到了正在做他们不需要做的工作的例子,或者我是否在这里误解了一些基本的东西。毕竟,如果我要显式地将令牌传递给 StartNew(),那么将它传递给 TaskFactory 构造函数的意义何在?
这是 TaskFactory
的 source:
构造函数:
public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
CheckMultiTaskContinuationOptions(continuationOptions);
CheckCreationOptions(creationOptions);
m_defaultCancellationToken = cancellationToken;
m_defaultScheduler = scheduler;
m_defaultCreationOptions = creationOptions;
m_defaultContinuationOptions = continuationOptions;
}
这是一个没有 CancellationToken
参数的重载及其实现方式:
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<TResult> function)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
}
如您所见,当您不使用带有 CancellationToken
参数的构造函数时,会使用构造函数中的 m_defaultCancellationToken
。
因此,仅当您使用没有 CancellationToken
重载的 TaskFactory.StartNew
时,在构造函数中传递 CancellationToken
才有用