c# TaskFactory 和 TaskScheduler 的关系和自定义
技术百科
月夜之吻
发布时间:2026-01-27
浏览: 次 TaskFactory 默认使用 TaskScheduler.Default,即基于线程池的调度器;它不执行任务,仅创建 Task 并交由指定 TaskScheduler 排队执行。
TaskFactory 默认用哪个 TaskScheduler?
TaskFactory 本身不执行任务,它只负责创建 
Task 实例;真正决定「何时、在哪一线程上运行」的是 TaskScheduler。默认情况下,TaskFactory 使用 TaskScheduler.Default —— 这个调度器背后是 .NET 的线程池(ThreadPool),也就是你调用 Task.Run(...) 或无参 new TaskFactory() 时实际走的路径。
关键点:不是 TaskFactory 决定调度,而是它把创建好的 Task 交给某个 TaskScheduler 去排队和执行。你可以显式传入自定义调度器,也可以改写 TaskFactory 的 Scheduler 属性。
怎么给 TaskFactory 指定自定义 TaskScheduler?
最直接的方式是在构造 TaskFactory 时传入自定义调度器实例:
var myScheduler = new ConcurrentExclusiveSchedulerPair().Scheduler; var factory = new TaskFactory(myScheduler);
之后所有通过该 factory 创建的任务(如 factory.StartNew(...))都会被提交到 myScheduler 执行。注意:Task.Run(...) 不会受此影响,它始终使用 TaskScheduler.Default。
常见错误:以为设置了 TaskScheduler.Default = myScheduler 就能全局生效 —— 这是无效的,Default 是只读属性,不能赋值。
-
TaskFactory的Scheduler属性可读可写,但修改它只影响后续创建的任务,不影响已排队的 - 若用
Task.Factory(静态实例),它的Scheduler也是可写的,但不建议全局修改,容易引发跨模块冲突 - 自定义调度器必须继承
TaskScheduler并实现QueueTask和GetScheduledTasks(后者仅调试需要)
自定义 TaskScheduler 最小可行实现长什么样?
一个最简可用的调度器只需把任务立即在当前线程同步执行(用于测试或 UI 线程强制同步场景):
public class SyncTaskScheduler : TaskScheduler, IDisposable
{
protected override void QueueTask(Task task) => TryExecuteTask(task);
protected override IEnumerable GetScheduledTasks() => Enumerable.Empty();
protected override void ExecuteTask(Task task) => TryExecuteTask(task);
public void Dispose() { }
}
这种调度器没有队列、不启新线程,StartNew 提交的任务会立刻在调用线程上运行。适合单元测试隔离异步行为,或 WinForms/WPF 中确保回调回到 UI 线程(此时应改用 WindowsFormsSynchronizationContext 或 DispatcherSynchronizationContext 封装)。
性能提示:不要在生产环境用纯同步调度器处理耗时操作,会阻塞调用方线程;真实自定义调度器通常要管理自己的线程/队列(比如限流、优先级、单线程串行等)。
TaskScheduler.UnobservedTaskException 是谁抛的?
这个事件由 TaskScheduler 触发,不是 TaskFactory。当某个 Task 抛出异常但从未被 await、Wait() 或读取 Exception 属性时,.NET 运行时会在该 Task 被 GC 回收前,通过其关联的 TaskScheduler 触发 UnobservedTaskException。
这意味着:如果你用了自定义调度器,且没重写 UnobservedTaskException 的触发逻辑(通常不需要重写),事件仍会按默认机制上报——但上报时机取决于该调度器如何管理任务生命周期。例如,某些自定义调度器延迟释放任务引用,可能导致异常“滞留”更久才被发现。
容易忽略的一点:即使你全程用 TaskFactory 创建任务,只要没处理异常,最终兜底的仍是调度器层面的未观测异常机制,而不是工厂本身。
# ai
# 是在
# 的是
# 就能
# 自己的
# 这是
# 如果你
# 你可以
# windows
# 重写
# 自定义
# win
# ui
# default
# c#
# .net
# 线程
# 异步
# 事件
# 封装
# 继承
# wpf
# 它只
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11键盘快捷键大全_Windows 11常用
- 一文教你快速开通网站LOGO图
- Win10如何更改网络连接_Windows10以太
- C#怎么创建控制台应用 C# Console Ap
- Win11怎么设置按流量计费_Win11限制后台流
- windows如何修改文件默认打开方式_windo
- Mac怎么查看活动监视器_理解Mac进程和资源占用
- 如何使用正则表达式批量替换重复的 *- 模式为固定
- Win11怎么关闭右下角弹窗_Win11拦截系统通
- C#如何序列化对象为XML XmlSerializ
- C#如何使用Channel C#通道实现异步通信
- 如何使用Golang实现文件追加操作_向已有文件追
- Win11怎么关闭定位服务 Win11禁止应用获取
- Win11怎么设置屏保时间_调整Win11屏幕保护
- c++中如何求一个数的平方根_c++ sqrt函数
- 如何在Golang中写入JSON文件_保存结构体数
- PHP中require语句后直接调用返回对象方法的
- 如何在Mac上搭建Golang开发环境_使用Hom
- Win11怎样安装搜狗输入法_Win11安装搜狗输
- ACF 教程:如何正确更新嵌套在多层 Group
- php下载安装后memory_limit怎么设置_
- VSC怎么快速定位PHP错误行_错误追踪设置法【方
- 如何在JavaScript中动态拼接PHP的bas
- 如何使用Golang捕获测试日志_Golang t
- 使用类变量定义字符串常量时的类型安全最佳实践
- php中::能访问全局变量吗_全局作用域与类作用域
- Win11怎么设置虚拟内存_Windows 11优
- Python随机数生成_random模块说明【指导
- VSC怎样在VSC中调试PHPAPI_接口调试技巧
- Win10如何卸载自带Edge_Win10彻底卸载
- C++如何使用std::async进行异步编程?(
- Windows10如何更改开机密码_Win10登录
- 如何使用Golang recover捕获panic
- c++ reinterpret_cast怎么用 c
- 如何在 Go 中正确反序列化 XML 多节点数组(
- Python深度学习实战教程_神经网络模型构建与训
- 如何使用正则表达式批量替换重复的“-”模式为固定字
- Win10系统映像怎么恢复 Win10使用系统映像
- php接口返回数据乱码怎么办_php接口调试编码问
- Python项目回滚策略_发布安全说明【指导】
- C++如何解析JSON数据?(nlohmann/j
- c++怎么设置线程优先级与cpu亲和性_c++ 多
- PHP cURL GET请求:正确设置请求头与身份
- Win11怎么设置默认输入法 Win11固定中文输
- windows 10应用商店区域怎么改_windo
- 如何在Golang中实现RPC异步返回_Golan
- LINUX的SELinux是什么_详解LINUX强
- Linux如何安装Tomcat应用服务器_Linu
- Win11怎么查看已连接wifi密码 Win11查
- Win11如何设置开机自动联网 Win11宽带连接

QQ客服