https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2

Toto je pokračování souběžnosti v sérii swift. Viz část 1 a část 2 pochopit základy

v této části se budeme zabývat následujícími tématy

  1. co je operace a je to život stavy
  2. vytvořit blok, NSInvocationOperation , a vlastní operace spustit úkoly async
  3. Jak zrušit operace
  4. co je operace fronty
  5. jak přidat operace v operacích fronty
  6. jak vytvořit závislosti mezi operacemi
  7. výhody provozních front nad GCD
  8. implementace expediční skupiny pomocí provozních front

operace jsou objektově orientovaný způsob zapouzdření práce, kterou chcete provádět asynchronně. Operace jsou navrženy tak, aby byly použity buď ve spojení s frontou operací, nebo samy o sobě

objekt operace je instancí třídy Operation or NSOperation (v rámci nadace), kterou používáte k zapouzdření práce, kterou má aplikace provádět.

samotná třída operace je abstraktní základní třída, která musí být podtříděna, aby mohla vykonávat jakoukoli užitečnou práci. Přesto, že je abstraktní, tato třída poskytuje značné množství infrastruktury, aby se minimalizovalo množství práce, kterou musíte udělat ve svých vlastních podtřídách. Rámec nadace navíc poskytuje dvě konkrétní podtřídy, které můžete použít tak, jak je s vaším stávajícím kódem.

Operations State

operace má stavový stroj, který představuje její životní cyklus. Existuje několik možných stavů, které se vyskytují v různých částech tohoto životního cyklu:

  • až bude instantiated, přejde do stavu isReady.
  • když jsme vyvolali metodu start, přejde do stavu isExecuting.
  • když úkol finished , přesune se do isFinished
  • když úkol probíhá a zavoláte cancel, pak přejde do stavu isCancelled před přechodem do stavu isFinished

existují hlavně tři způsoby, jak vytvořit operace

Blokoperace (třída betonu)

třída, kterou používáte jako-je spustit jeden nebo více objektů bloku současně. Protože může spustit více než jeden blok, objekt operace bloku pracuje pomocí sémantické skupiny; pouze tehdy, když všechny přidružené bloky dokončily provádění, je samotná operace považována za dokončenou.. V blokovém provozu můžete využít závislosti na provozu, KVO, oznámení a zrušení .

jak je znázorněno na obrázku 1, provedli jsme tento kód async , což znamená, že se okamžitě vrátí, ale špatnou zprávou je, že zablokuje hlavní vlákno, protože operation.start() byl vyvolán na hlavním vlákně

provozní objekty se ve výchozím nastavení provádějí synchronním způsobem — to znamená, že vykonávají svůj úkol v podprocesu, který volá jejich metodu start.

Obrázek 1

co to sakra je synchronní způsobem a spustit jeden nebo více blokových objektů současně.

jak je znázorněno na obrázku 1.0.1 jak můžete vidět úkoly / bloky přidané do samotné operace bloku prováděné současně, ale synchronní způsob běhu bloku znamená, že zablokoval vlákno, při kterém je start volán, v našem případě je to hlavní vlákno

obrázek 1.0.1

jak je znázorněno na obrázku obrázek 1.0.2, protože voláme metodu start na jiném vlákně, zablokuje toto vlákno

obrázek 1.0.2

jak je znázorněno na obrázku obrázek 1.0.3, můžeme také přidat blok dokončení, který bude volat, když budou provedeny všechny souběžné bloky

obrázek 1.0.3

spusťte blokovou operaci současně

, jak je znázorněno na obrázku 1.1 protože voláme metodu start() na podprocesu na pozadí, provede svůj úkol v podprocesu. Existuje skvělý způsob, jak to udělat pomocí operace fronta a uvidíme to později.

obrázek 1.1

Nsinvocationoperace (třída betonu)

třída, kterou používáte k vytvoření provozního objektu založeného na objektu a voliči z vaší aplikace.

v cíli C můžeme vytvořit NSInvocationOperation, zatímco není k dispozici ve službě Swift.

https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationObjects/OperationObjects.html#//apple_ref/doc/uid/TP40008091-CH101-SW6

3. Vlastní operace

Subclassing Operation vám dává úplnou kontrolu nad implementací vašich vlastních operací, včetně možnosti změnit výchozí způsob, jakým vaše operace provádí a hlásí svůj stav.

jak je znázorněno na obrázku 2, vytvořili jsme vlastní operace podtřídou it z Operation základní třídy a přepsali její metodu main. Když podtřídy dáte svůj úkol na main metoda. Implementovali jsme nesouběžnou vlastní operaci a v tomto případě jsme zablokovali hlavní vlákno

Obrázek 2

pokud plánujete provádět operace ručně a přesto chcete, aby byly spuštěny asynchronně, musíte podniknout příslušné kroky, abyste se ujistili, že ano. To provedete definováním objektu operace jako souběžné operace.

jak je znázorněno na obrázku 3 provedli jsme následující kroky k provedení úkolu souběžně

  1. vytvořená podtřída MyConcurrentQueue . Překlep: Název by měl být MyConcurrentOperations
  2. volání start() metoda zavolá main() metoda na podprocesu pozadí
  3. na hlavní metodě jsme definovali náš úkol a jednu věc, kterou je třeba poznamenat, zajišťujeme zrušení případu také
  4. při volání cancel při vlastní operaci přejde do stavu isCancelled a přeruší smyčku a jak je znázorněno na obrázku 3 vytiskne pouze 39487 položek

obrázek 3

fronty operací

  1. fronty operací jsou Cocoa na vysoké úrovni abstrakce na GCD
  2. pomocí Fronty operací uvidíte skutečnou sílu operací, namísto spuštění operace sami, dáte ji do fronty operací, která pak zpracovává plánování a provádění.
  3. Provozní fronty jsou objektově orientovaný způsob zapouzdření práce, kterou chcete provádět asynchronně.
  4. přidáte operations (úkoly/práce) na operation queue a diskutovali jsme o tom, jak můžeme vytvořit operace pomocí dvou metod.

přidat operace

jak je znázorněno na obrázku 4 vytvořili jsme dvě operace (pomocí bloku) a přidali je do fronty provozu. Operace fronta zahájila obě operace na nějakém podprocesu na pozadí a provedla je. Není třeba volat start() metodu na vlastní vlákno 🆒. Když přidáme operaci do fronty operací, spustí se, jakmile bude připravena

obrázek 4

jak je znázorněno na obrázku 5 Právě jsme provedli úkol sériově, nebo můžete říci, že jsme implementovali sériovou frontu pomocí provozních Front naleznete v mé části 1 pokud nevíte, co je sériová fronta nastavením maxConcurrentOperationCount = 1

maxConcurrentOperationCount →maximální počet operací ve frontě, které lze provést současně. Výchozí hodnota je -1, což znamená nechat systém rozhodnout

obrázek 5

nastavením maxConcurrentOperationCount = 2 jsme vytvořili souběžnou frontu a nyní se úkoly provádějí souběžně, jak je znázorněno na obrázku 6

obrázek 6

závislosti operací

jak je znázorněno na obrázku 7, Znovu jsme vytvořili sériovou frontu přidáním závislostí mezi dvěma úkoly. Vytvořili jsme dvě blokové operace a říkáme, že nezačínejte úkol 1, dokud nebude úkol 2 dokončen voláním blockOperations1.addDependency(blockOperations2)

Obrázek 7

implementace skupiny odeslání pomocí fronty operací

v části 2 jsme použili funkci skupiny odeslání GCD k blokování podprocesu, dokud jeden nebo více úkolů nedokončil provádění. Jak je znázorněno na obrázku 8, implementovali jsme stejné chování pomocí provozních Front pomocí závislostí. To je velmi užitečné, pokud nemůžete dosáhnout pokroku, dokud nebudou dokončeny všechny zadané úkoly.

jak je znázorněno na obrázku 8 máme tři úkoly a chtěli jsme spustit souběžně a po dokončení všech úkolů musíme zavolat nějakou metodu, která indikuje, že všechny úkoly byly dokončeny a co jsme udělali

  1. vytvořili frontu operací
  2. vytvořili tři blokové operace, které budou provádět úkoly
  3. vytvořili operaci bloku dokončení (blockOperations4), která se spustí, když budou všechny tři úkoly dokončeny
  4. Vyrobeno blockOperations4 v závislosti na blockOperations1, blockOperations2 a blockOperations3 což znamená, že blockoperations4 se spustí po dokončení všech tří úkolů
  5. waitUntilFinished → Blokuje provádění aktuálního vlákna, dokud objekt operace nedokončí svůj úkol, protože nechceme blokovat aktuální vlákno, které je hlavní, přiřadíme jej false
  6. spusťte tento kód a „veškerá operace je dokončena“ se vytiskne, když budou dokončeny task1, task2 a task3

Obrázek 8

jak je znázorněno na obrázku 9, zablokujeme hlavní vlákno nastavením waitUntilFinished = true. , takže otázkou je, kdy je to užitečné, a odpověď dostanete v další části

obrázek 9

jak je znázorněno na obrázku 10 implementovali jsme chování expediční skupiny pomocí operace fronta bez použití jakýchkoli závislostí, co jsme použili waitUntilFinished funkci vhodně . Pokud jste v podprocesu na pozadí, můžete toto vlákno zablokovat, abyste dosáhli tohoto chování. Záměrně jsem přepnul na podproces pozadí pomocí metody DispatchQueue.global().async viz část 1, abychom pochopili tento kód

řekli jsme operation queue spustit úkol 1, úkol 2 a úkol 3 na operation queue a blokovat aktuální vlákno, dokud tyto souběžné úkoly nedokončí jejich provádění

obrázek 10

výhody provozních Front přes GCD

  1. operační API poskytuje podporu závislostí. Můžete vytvářet složité závislosti mezi úkoly velmi snadno, i když v GCD toho můžete dosáhnout, ale musíte udělat hodně práce.
  2. třídy Nsoperace a NSOperationQueue mají řadu vlastností, které lze pozorovat pomocí KVO (Key Value Observing). To je další důležitá výhoda, pokud chcete sledovat stav operace nebo fronty operací.
  3. operace lze pozastavit, obnovit a zrušit. Jakmile odešlete úkol pomocí Grand Central Dispatch, již nemáte kontrolu ani přehled o provádění tohoto úkolu. NSOperation API je v tomto ohledu flexibilnější a dává vývojáři kontrolu nad životním cyklem operace
  4. NSOperationQueue také přidává řadu výhod do mixu. Můžete například určit maximální počet operací ve frontě, které mohou běžet současně. Díky tomu je snadné kontrolovat, kolik operací běží současně, nebo vytvořit frontu sériových operací.

Nadcházející

v další části se podíváme na skutečný případ použití Vytvoření vlastní operace

užitečné odkazy

· https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationObjects/OperationObjects.html#//apple_ref/doc/uid/TP40008091-CH101-SW1

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.