C# 当前任务计划程序是否流入ThreadPool.QueueUserWorkItem回调?
当前任务计划程序是否作为执行上下文流的一部分流入C# 当前任务计划程序是否流入ThreadPool.QueueUserWorkItem回调?,c#,.net,.net-core,async-await,task-parallel-library,C#,.net,.net Core,Async Await,Task Parallel Library,当前任务计划程序是否作为执行上下文流的一部分流入ThreadPool.QueueUserWorkItem回调 我希望它不会,因此应该传递以下调试断言。我在网上找不到任何证实 var scheduler = new CustomTaskScheduler(); await Task.Factory.StartNew(async () => { Debug.Assert(TaskScheduler.Current == scheduler); var tcs = new Ta
ThreadPool.QueueUserWorkItem
回调
我希望它不会,因此应该传递以下调试断言。我在网上找不到任何证实
var scheduler = new CustomTaskScheduler();
await Task.Factory.StartNew(async () =>
{
Debug.Assert(TaskScheduler.Current == scheduler);
var tcs = new TaskCompletionSource<bool>();
ThreadPool.QueueUserWorkItem(_ =>
{
Debug.Assert(TaskScheduler.Current != scheduler);
Debug.Assert(TaskScheduler.Current == TaskScheduler.Default);
tcs.SetResult(true);
});
await tcs.Task;
Debug.Assert(TaskScheduler.Current == scheduler);
},
CancellationToken.None,
TaskCreationOptions.None,
scheduler).Unwrap();
var调度器=新建CustomTaskScheduler();
等待Task.Factory.StartNew(异步()=>
{
Assert(TaskScheduler.Current==scheduler);
var tcs=new TaskCompletionSource();
ThreadPool.QueueUserWorkItem(=>
{
Assert(TaskScheduler.Current!=调度程序);
Assert(TaskScheduler.Current==TaskScheduler.Default);
tcs.SetResult(真);
});
等待tcs任务;
Assert(TaskScheduler.Current==scheduler);
},
取消令牌。无,
任务创建选项。无,
调度器)。展开();
当前任务计划程序是否作为执行上下文流的一部分流入ThreadPool.QueueUserWorkItem
回调
对我未来的自己:不,没有,正如预期的那样。下面是一个简单的CustomTaskScheduler
来测试相关代码:
public class CustomTaskScheduler : TaskScheduler
{
protected override IEnumerable<Task>? GetScheduledTasks()
{
throw new NotImplementedException();
}
protected override void QueueTask(Task task)
{
ThreadPool.QueueUserWorkItem(t =>
base.TryExecuteTask((Task)t!), task);
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return false;
}
}
QueueUserWorkItem
queues处理线程池中的下一个可用线程,该线程池由默认任务计划程序管理。如果您想使用自定义TaskScheduler,那么这是使用StartNew
的少数有效原因之一@MichaelRandall,实际上我不想使用自定义任务调度程序。相反,我希望确保当当前环境任务调度器为非默认值时,如果使用QueueUserWorkItem
/UnsafeQueueUserWorkItem
,我将返回默认值。因此,现有的行为正是我所需要的。@MichaelRandall,除此之外,它很可能位于ThreadPool
线程上,并且仍然具有TaskScheduler.Current!=TaskScheduler.Default
。是的,我同意您可以在任何线程上设置当前任务计划程序,如果您不能设置,这将是非常有限的。我的观点是,ThreadPool.QueueUserWorkItem
和许多其他TPL方法都会出现这种行为,除非它们特别允许您设置调度程序,或者具有其他高级选项。我个人认为问题和答案都很好,而且很多信息(正如stephen toub(意译)曾经说过的)就像空气一样,你通常不必担心它。。。直到你do@MichaelRandall,同意。我认为这是一个合理的假设,但我真的想验证一下:)这样做比深入研究更简单。
var scheduler = new CustomTaskScheduler();
await Task.Factory.StartNew(async () =>
{
Debug.Assert(TaskScheduler.Current == scheduler);
var tcs = new TaskCompletionSource<bool>();
ThreadPool.QueueUserWorkItem(_ =>
{
Debug.Assert(TaskScheduler.Current != scheduler);
Debug.Assert(TaskScheduler.Current == TaskScheduler.Default);
tcs.SetResult(true);
});
await tcs.Task;
Debug.Assert(TaskScheduler.Current == scheduler);
},
CancellationToken.None,
TaskCreationOptions.None,
scheduler).Unwrap();