W miarę możliwości należy stosować asynchroniczne wersje operacji zamiast synchronicznych.
Operacje synchroniczne są wykonywane, gdy tylko kod poleci ich wykonanie, a kod oczekuje na ich zakończenie. W konsekwencji takie operacje działają w fazie wykonywania kodu aplikacji w pętli klatki. Jeśli operacja synchroniczna jest wykonywana zbyt długo, wówczas operacja wydłuża czas pętli klatki, co może spowodować zatrzymanie wyświetlania lub wyświetlanie z przerwami.
Gdy kod jest wykonywany jako operacja asynchroniczna, nie musi być wykonywany natychmiast. W przypadku operacji asynchronicznych trwa wykonywanie właściwego kodu oraz innego kodu aplikacji w bieżącym wątku wykonania. Następnie środowisko wykonawcze jak najszybciej wykonuje operację, podejmując próby uniknięcia problemów z renderowaniem. W niektórych przypadkach wykonywanie odbywa się w tle i kod nie jest w ogóle wykonywany w ramach pętli klatki w środowisku wykonawczym. Gdy operacja zostanie ukończona, środowisko wykonawcze wywoła zdarzenie, a kod może wykryć to zdarzenie w celu wykonania dodatkowych operacji.
Operacje asynchroniczne są zaplanowane i dzielone w celu uniknięcia problemów z renderowaniem. W konsekwencji aplikacje, w których stosowane są asynchroniczne wersje operacji, działają dużo szybciej. Więcej informacji zawiera sekcja
Wydajność subiektywna a wydajność rzeczywista
.
Istnieje jednak narzut ujęty w operacjach uruchomionych asynchronicznie. Rzeczywisty czas wykonania może być dłuższy dla operacji asynchronicznych, szczególnie dotyczący operacji, których wykonanie zajmuje niewiele czasu.
W środowisku wykonawczym wiele operacji jest wykonywanych w sposób synchroniczny lub asynchroniczny i nie ma możliwości wybrania sposobu ich wykonywania. Jednak w środowisku Adobe AIR istnieją trzy typy operacji, które mogą być wykonywane synchronicznie lub asynchronicznie:
-
Operacje klasy File i FileStream
Wiele operacji klasy File może być wykonywanych synchronicznie lub asynchronicznie. Na przykład: wszystkie metody kopiowania lub usuwania plików i katalogów oraz metody wyświetlania zawartości katalogów mają wersje asynchroniczne. Te metody mają przyrostek „Async” dodany do nazwy wersji asynchronicznej. Na przykład: w celu asynchronicznego usuwania pliku należy wywołać metodę
File.deleteFileAsync()
zamiast metody
File.deleteFile()
.
W przypadku stosowania obiektu FileStream do odczytywania z pliku lub zapisywania do pliku sposób otwierania obiektu FileStream określa, czy operacje zapisu i odczytu będą wykonywane w sposób asynchroniczny. Dla wszystkich operacji asynchronicznych należy stosować metodę
FileStream.openAsync()
. Zapis danych jest wykonywany metodą asynchroniczną. Odczyt danych odbywa się porcjami, dlatego w danym momencie dostępna jest tylko jedna porcja danych. I odwrotnie — w trybie synchronicznym obiekt FileStream odczytuje cały plik zanim przystąpi do wykonywania kodu.
-
Operacje na lokalnej bazie danych SQL
Podczas pracy z lokalną bazą danych SQL wszystkie operacje wykonywane przez obiekt SQLConnection są wykonywane w trybie synchronicznym lub asynchronicznym. W celu określenia, że operacje będą wykonywane asynchronicznie, należy otworzyć połączenie z bazą danych, korzystając z metody
SQLConnection.openAsync()
zamiast metody
SQLConnection.open()
. Jeśli operacje bazy danych działają asynchronicznie, wówczas są wykonywane w tle. Mechanizm bazy danych w ogóle nie działa w pętli klatki środowiska wykonawczego, dlatego prawdopodobieństwo, że operacje bazodanowe będą powodowały problemy z renderowaniem, jest dużo niższe.
Dodatkowe strategie umożliwiające zwiększenie wydajności korzystania z lokalnej bazy danych SQL zawiera sekcja
Wydajność bazy danych SQL
.
-
Autonomiczne moduły cieniujące Pixel Bender
Klasa ShaderJob umożliwia uruchomienie obrazu lub zestawu danych za pośrednictwem modułu cieniującego Pixel Bender oraz uzyskanie dostępu do nieprzetworzonych danych wynikowych. Domyślnie po wywołaniu metody
ShaderJob.start()
moduł cieniujący działa w trybie asynchronicznym. To wykonanie odbywa się w tle bez wykorzystania pętli klatki środowiska wykonawczego. W celu wymuszenia synchronicznego działania obiektu ShaderJob (co nie jest zalecane) należy przekazać
true
do pierwszego parametru metody
start()
.
Dostępne są zatem wbudowane mechanizmy umożliwiające asynchroniczne wykonywanie kodu, a oprócz tego programista może zapisywać kod w taki sposób, który zapewni jego asynchroniczne wykonywanie. W przypadku pisania kodu przeznaczonego do wykonywania potencjalnie długotrwałego zadania strukturę kodu można zdefiniować w taki sposób, aby kod był wykonywany w częściach. Jeśli kod jest podzielony na części, wówczas środowisko wykonawcze może wykonywać operacje renderowania pomiędzy blokami wykonywanego kodu, dzięki czemu występowanie problemów z renderowaniem będzie mniej prawdopodobne.
Poniżej przedstawiono kilka technik dzielenia kodu. Głównym celem tych technik jest taki zapis kodu, który w dowolnym czasie będzie gwarantował wykonanie tylko części operacji. Programista może śledzić, jakie operacje wykonuje kod oraz kiedy przestaje działać. Za pomocą mechanizmu, takiego jak obiekt Timer, programista może wielokrotnie sprawdzać, jaka część pracy została do wykonania, oraz wykonywać w porcjach dodatkowe operacje do zakończenia pracy.
Istnieje kilka predefiniowanych wzorców tworzenia struktury kodu w taki sposób, który zapewni podział operacji. Poniższe artykuły i biblioteki kodu opisują te wzorce i zawierają kod, który ułatwia implementowanie tych wzorców w aplikacjach: