Chromium Chronicle #1: Best Practices für die Aufgabenplanung

Das Chrome-Team ist stolz, Chromium Chronicle vorzustellen, eine monatliche speziell für Chromium-Entwickler, Entwickler, die die Browser.

Chromium Chronicle konzentriert sich vor allem darauf, technisches Wissen zu vermitteln. und Best Practices zum Schreiben, Entwickeln und Testen von Chrome. Unser Plan ist es, Themen, die für Chromium-Entwickler relevant und nützlich sind, z. B. Code Gesundheit, hilfreiche Tools, Unittests, Barrierefreiheit und vieles mehr! Jeder Artikel werden von Chrome-Entwicklern verfasst und bearbeitet.

Wir freuen uns auf diese neue Serie und hoffen, du auch! Bist du bereit? Unten seht ihr die erste Folge.

Best Practices für die Aufgabenplanung

Folge 1:von Gabriel Charette in Montreal, PQ (April 2019)
Vorherige Folgen

Chrome-Code, der eine asynchrone Ausführung in der Verarbeitung erfordert, sendet in der Regel Aufgaben Sequenzen anwenden. Sequenzen sind von Chrome verwaltete „virtuelle Threads“ und sind die Erstellung eines eigenen Threads bevorzugt. Wie kann ein Objekt in welcher Reihenfolge sie posten soll?

Don'ts

Das alte Muster besteht darin, einen SequencedTaskRunner vom Ersteller zu erhalten:

Foo::Foo(scoped_refptr backend_task_runner)
    : backend_task_runner_(std::move(backend_task_runner)) {}
Do

Das bevorzugte Paradigma ist das Erstellen eines unabhängigen SequencedTaskRunners:

Foo::Foo()
    : backend_task_runner_(
          base::CreateSequencedTaskRunnerWithTraits({
              base::MayBlock(), base::TaskPriority::BEST_EFFORT})) {}

Es ist einfacher zu lesen und zu schreiben, da alle Informationen lokal sind und ohne das Risiko von Abhängigkeiten mit anderen Aufgaben.

Dieses Modell ist auch beim Testen besser. Anstelle der Injektion von Task-Runner manuell ausführen, können Tests eine kontrollierte Aufgabenumgebung instanziieren. zur Verwaltung der Aufgaben von Foo:

class FooTest : public testing::Test {
 public
  (...)
 protected:
  base::test::TaskEnvironment task_environment_;
  Foo foo_;
};

Wenn TaskEnvironment an erster Stelle in der Befestigung steht, wird es automatisch verwaltet die Aufgabenumgebung während der gesamten Lebensdauer von Foo. Die TaskEnvironment erfasst die Anfrage-bei-Konstruktion von Foo, um einen SequencedTaskRunner zu erstellen und seine Aufgaben unter jedem FooTest verwaltet.

Um das Ergebnis der asynchronen Ausführung zu testen, verwenden Sie die Methode RunLoop::Run()+QuitClosure()-Modell:

TEST_F(FooTest, TestAsyncWork) {
  RunLoop run_loop;
  foo_.BeginAsyncWork(run_loop.QuitClosure());
  run_loop.Run();
  EXPECT_TRUE(foo_.work_done());
}

Wird RunUntilIdle() vorgezogen, da diese instabil sein kann, wenn die asynchrone Aufgaben außerhalb des Aufgabenbereichs der TaskEnvironment z.B. ein Systemereignis. Verwenden Sie RunUntilIdle() daher mit Vorsicht.

Möchtest du mehr darüber erfahren? Lesen Sie unsere Dokumentation zu Threading und Aufgaben. oder lassen Sie sich an der Migration zu TaskEnvironment beteiligen!