co un() 是 swoolecoroutinescheduler 的封装,开箱即用但不可复用;new coroutinescheduler() 提供完整生命周期控制,支持多次 add、参数配置与异常处理。

Co un() 和 new CoroutineScheduler() 有什么区别
两者本质是同一套机制:Co
un() 是 SwooleCoroutineScheduler 的封装,就像 echo 是 print 的别名。调用 Co
un() 时内部会 new 一个 Scheduler 实例并执行 start()。
关键差异在控制粒度:
-
Co un()是“开箱即用”,适合脚本入口或简单并发任务,但无法复用调度器、无法中途干预调度逻辑 -
new CoroutineScheduler()提供完整生命周期控制:可多次add()、可set()参数、可自定义异常处理器、可判断是否已启动(isRunning()) - 不能嵌套调用
Co un();而多个Scheduler实例可共存(只要不同时start())
add() 传函数时为什么不能直接写 task1() 而要写 task1
常见错误是这样写:$scheduler->add(task1()); —— 这会立即执行 task1(),把它的返回值(通常是 null)传给 add(),导致调度器什么也没加进去,运行时静默失败。
正确做法是只传函数引用:
- 普通函数名:
$scheduler->add('task1');或$scheduler->add(task1);(PHP 8.1+ 支持无引号函数名) - 匿名函数:
$scheduler->add(function () { Co::sleep(1); echo "done "; }); - 带参数的匿名函数:
$scheduler->add(fn() => doWork($arg));(注意变量捕获时机)
传参必须用 add(callable $fn, array $args = []) 的第二个参数,否则闭包里用到的外部变量可能在调度时已失效。
协程调度器启动后,后续代码还执行吗
不执行——这是最容易忽略的陷阱。$scheduler->start() 是阻塞调用,它会进入事件循环,直到所有协程结束、没有待处理 IO、且无新任务加入,才会返回。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
看这个典型反例:
$scheduler = new CoScheduler(); $scheduler->add(fn() => Co::sleep(1)); $scheduler->start(); echo "this line never runs "; // ← 永远不会输出
如果你需要调度完继续执行,有且只有两种方式:
- 把后续逻辑也包装成协程任务,用
add()加入调度器末尾 - 改用
go()+SwooleEvent::wait()(仅限旧版兼容场景,不推荐)
注意:Co
un() 同样阻塞,它的回调执行完才退出整个进程。
如何捕获协程内未处理的异常
协程中抛出未 catch 的异常,默认会导致整个进程崩溃(不是单个协程退出)。必须显式设置异常处理器:
- 全局方式(推荐):
$scheduler->setExceptionHandler(fn($throwable) => error_log($throwable->getMessage())); - 也可用
SwooleCoroutineScheduler::setExceptionHandler()静态方法,效果相同 - 每个协程仍需自己
try/catch处理业务异常;setExceptionHandler只兜底“漏网之鱼”
特别注意:如果在 add() 的函数里用了 defer(),异常发生时 defer 仍会执行——这是资源清理的关键保障点。










