Zespół Chrome z dumą przedstawia Chromium Chronicle, miesięczną stworzonych z myślą o użytkownikach Chromium, przeglądarki.
Chromium Chronicle kładzie nacisk głównie na przekazywanie wiedzy technicznej oraz sprawdzone metody pisania, tworzenia i testowania Chrome. Planujemy udostępnić tematy, które są istotne i przydatne dla programistów Chromium (np. kod), zdrowie, przydatne narzędzia, testy jednostkowe, ułatwienia dostępu i nie tylko. Każdy artykuł będzie napisana i edytowana przez inżynierów Chrome.
Ta nowa seria bardzo się cieszy i mamy nadzieję, że Ty też! Wszystko gotowe? Obejrzyj pierwszy odcinek poniżej.
Sprawdzone metody dotyczące planowania zadań
Odcinek 1: Gabriel Charette, Montreal, PQ (kwiecień 2019 r.)
Poprzednie odcinki
Kod Chrome, który wymaga asynchronicznego wykonywania w trakcie procesu, zwykle publikuje zadania do sekwencji. Sekwencje to zarządzane przez Chrome „wątki wirtualne” i są wolisz utworzyć własny wątek. Jak obiekt i w której kolejności wysłać wiadomość?
Stary model polega na otrzymaniu od twórcy elementu SequencedTaskRunner:
Foo::Foo(scoped_refptr
Preferowanym modelem jest utworzenie niezależnego elementu SequencedTaskRunner:
Foo::Foo()
: backend_task_runner_(
base::CreateSequencedTaskRunnerWithTraits({
base::MayBlock(), base::TaskPriority::BEST_EFFORT})) {}
Są one łatwiejsze do czytania i pisania, ponieważ wszystkie informacje są dostępne lokalnie, nie istnieje ryzyko współdziałania z niepowiązanymi ze sobą zadaniami.
Taki model jest też lepszy w przypadku testowania. Zamiast wstrzykiwać uruchamiających zadania ręcznie, testy mogą inicjować kontrolowane środowisko zadań aby zarządzać zadaniami Foo:
class FooTest : public testing::Test {
public
(...)
protected:
base::test::TaskEnvironment task_environment_;
Foo foo_;
};
Ustawienie TaskEnvironment na pierwszym planie w naturalny sposób zarządza środowiskiem zadań przez cały czas istnienia Foo. Środowisko zadań przechwytuje żądanie Foo w celu utworzenia obiektu SequencedTaskRunner, będzie zarządzać zadaniami w ramach każdego testu FooTest.
Aby sprawdzić wynik wykonania asynchronicznego, użyj
Model RunLoop::Run()+QuitClosure()
:
TEST_F(FooTest, TestAsyncWork) {
RunLoop run_loop;
foo_.BeginAsyncWork(run_loop.QuitClosure());
run_loop.Run();
EXPECT_TRUE(foo_.work_done());
}
Jest to lepsze rozwiązanie niż RunUntilIdle(), który może działać niestabilnie, jeśli funkcja asynchroniczna
zadanie obejmuje zadanie spoza zakresu TaskEnvironment,
np. jest zdarzeniem systemowym, więc używaj RunUntilIdle()
z rozwagą.
Chcesz dowiedzieć się więcej? Zapoznaj się z dokumentacją dotyczącą podziału na wątki i zadań. lub weź udział w migracji do TaskEnvironment.