Chrome 团队很荣幸地向大家推出 Chromium Chronicle, 该系列文章面向的是 Chromium 开发者, 。
《Chromium Chronicle》将主要侧重于传播技术知识 以及编写、构建和测试 Chrome 的最佳做法我们计划 与 Chromium 开发者相关且实用的主题,例如代码 运行状况、实用工具、单元测试、无障碍功能等等!每篇文章 将由 Chrome 工程师编写和修改。
我们对这个新的系列充满期待,希望您也是如此!准备好深入探索了吗? 欢迎观看下面的第一集视频!
任务安排最佳做法
第 1 集:作者:Gabriel Charette in Montréal,PQ(2019 年 4 月)
上一集
需要进程内异步执行的 Chrome 代码通常会发布任务 序列。序列是 Chrome 管理的“虚拟线程”和 倾向于自行创建会话。对象是如何 知道发布到哪个序列?
旧范式是从创建者那里接收 SequencedTaskRunner:
Foo::Foo(scoped_refptr
首选范式是创建独立的 SequencedTaskRunner:
Foo::Foo()
: backend_task_runner_(
base::CreateSequencedTaskRunnerWithTraits({
base::MayBlock(), base::TaskPriority::BEST_EFFORT})) {}
这样更易于读写,因为所有信息都是本地信息 不存在与无关任务相互依赖的风险。
这种范式在测试方面也更好。无需注入 任务运行程序,测试可以实例化受控的任务环境 管理 Foo 的任务:
class FooTest : public testing::Test {
public
(...)
protected:
base::test::TaskEnvironment task_environment_;
Foo foo_;
};
在固件中优先使用 TaskEnvironment 可以自然地确保它 在 Foo 的整个生命周期内管理任务环境。TaskEnvironment 将捕获 Foo 的构建请求以创建 SequencedTaskRunner 并 将在每次 FooTest 下管理其任务。
要测试异步执行的结果,请使用
RunLoop::Run()+QuitClosure()
范式:
TEST_F(FooTest, TestAsyncWork) {
RunLoop run_loop;
foo_.BeginAsyncWork(run_loop.QuitClosure());
run_loop.Run();
EXPECT_TRUE(foo_.work_done());
}
这是首选 RunUntilIdle(),如果使用异步脚本,
工作负载涉及到 TaskEnvironment 权限范围之外的任务,
例如是系统事件,因此请谨慎使用 RunUntilIdle()
。
希望了解更多信息?阅读我们关于线程处理和任务的文档 或参与迁移到 TaskEnvironment!