开启task_enable_coroutine后,ontask中可直接使用协程api;需配合enable_coroutine=true,参数变为swoole\server\task对象,必须调用$task->finish(),且仅支持swoole≥4.4.0。

task_enable_coroutine开启后,onTask里能直接用协程API
不开启时,onTask 回调运行在普通同步上下文中,调用 Swoole\Coroutine\MySQL 或 co::sleep() 会直接报错:Fatal error: Uncaught Swoole\Error: Must be called in the coroutine context。开启后,Swoole 在每次执行 onTask 前自动创建一个协程,你写的代码就像在 go() 里一样自然。
关键点:
-
task_enable_coroutine必须和enable_coroutine => true同时生效(后者是全局协程开关,默认已开启) - 开启后,
onTask的第二个参数类型变为Swoole\Server\Task对象,而不是旧版的$taskId、$srcWorkerId等离散参数 - 不能再用
$server->finish(),必须调用$task->finish()返回结果,否则数据收不到
不开 task_enable_coroutine 也能跑,但得自己套 go()
如果你关了 task_enable_coroutine(设为 false),又想在 onTask 中发 HTTP 请求或查数据库,唯一办法是手动启动协程:
<pre class="brush:php;toolbar:false;">$server->on('Task', function ($server, $taskId, $srcWorkerId, $data) {
go(function () use ($data) {
$client = new Swoole\Coroutine\Http\Client('api.example.com', 80);
$client->get('/status');
$server->finish($client->getBody());
});
});
这种写法不仅冗余,还容易漏掉错误处理、超时控制,更麻烦的是:协程内无法访问 $server
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
$server 不是协程安全对象),$server->finish() 调用会失败 —— 你得把 $server 传进去或改用全局引用,极易出错。
task_enable_coroutine 和 task_async 的关系
task_async 是 Swoole 早期为 Task 进程引入异步能力的尝试,但它存在严重设计缺陷:
- 它让 Task 进程内部也启用 Reactor,导致上下文混乱,
Server::finish()可能写到错误的任务 ID - 与协程机制冲突,开启
enable_coroutine后task_async会被忽略甚至引发崩溃 - 官方已在新版本中废弃该配置,2026 年起全面移除,文档和代码里都不再支持
所以现在只有一条路:用 task_enable_coroutine => true + Swoole\Server\Task 对象 + $task->finish(),其他组合都是过时或危险的。
容易被忽略的兼容性坑
最常踩的不是功能不会用,而是环境没对齐:
-
task_enable_coroutine仅在 Swoole ≥ 4.4.0 有效;低于此版本设了也无效,且不会警告 - PHP 版本必须 ≥ 7.0(协程底层依赖 Fiber,PHP 8.1+ 更稳定)
- 如果用了
opcache.enable_cli=1,某些协程客户端(如Swoole\Coroutine\Redis)可能因类加载顺序异常而报Class not found - 在
onShutdown回调里不能用协程 API —— 此时协程调度器已退出,哪怕开了task_enable_coroutine也没用
真正要验证是否生效,别只看配置有没有设,直接在 onTask 里写一行 co::sleep(0.01),不报错就说明环境通了。










