Jenže to tak úplně není. Když dělám nějaký skript, tak v 90% šáhnu po Pythonu, protože ten skript spustím párkrát, ale mám ho napsaný velmi rychle. To jestli mi to běží hodinu nebo dvě mě opravdu netrápí, ale jestli to dělám 10min nebo hodinu už rozdíl je. To vůbec nemá nic společného, že bych C nebo Go nepoužil jindy, ale prostě v tom Pythonu se většinou píše o několik řádů rychleji, navíc Python má podporu skoro pro všechno narozdíl od Go a Rust. Takže u nás frčí kombinace Java pro microservices a Python pro skripty. Hlavně u HTTP requestů (REST API) jsem nikdy nedělal s ničím co by bylo tak snadné a účinné, jako je Python a requests, to samé pro MongoDB.
Kdyby byl Python 2x pomalejší, tak by to mohlo stát za úvahu, jenže když si vezmeme Great Language Shootout, tak nějaký numerický výpočet v Pythonu může být klidně 180x pomalejší, než v Rustu nebo C. Takže pak nejde o to, jestli stojí za to si usnadnit práci a mít pomalejší program, ale jestli je výsledný program vůbec použitelný, nebo ne.
“výkon díky zero-overhead abstrakcím při trošku rozumném návrhu běží jako blesk”
Ty tzv. “zero-cost” abstrakce jsou konkrétně v Rustu trochu “wishful thinking”, popis “jako blesk” bych použil možná u Fortranu, Rust je extra bezpečný, ale platí se za to ztrátou části výkonu (což je naprosto logické, člověk si musí vybrat).
Zero-cost je blbý termín, začal jsem používat zero-overhead, což lépe vystihuje, že použití abstrakce je stejně "drahé", jako kdyby se (principiálně) ten samý kód napsal v C nebo assembleru.
Co se týče bezpečnosti, tak podle toho, jak rozumím možnostem optimalizace kompilátoru, Rust umožňuje díky jistotě, že se některé věci nestanou, říznout do generování kódu daleko důrazněji. Overhead lze očekávat třeba u indexování vektoru, jenže tam existují možnosti z toho vyjít pomocí metod typu get_unchecked(), které se zase ale AFAIK s výhodou používají třeba v přístupech přes iterátor, jelikož ten ví, kam může sáhnout a kam už ne. Takže obecně ano, určitě existují pořád situace, kde člověk za bezpečnost platí, ale tak zásadní problém tam snad není.
“Rust umožňuje díky jistotě, že se některé věci nestanou […]”
To se týká každého jazyka, třeba Julia díky typovému systému také brutálně optimalizuje. U toho indexování pole má Rust pořád dost mezery (má-li být stoprocentně bezpečné), některé jazyky ho umí bez kontrol a výjimek za běhu, to chce ale silnější typový systém, tady taky Rust zaostává. Obecně jo, různé unchecked/unsafe hacky pomáhají, ostatně standardní knihovna je jich plná, ale to je dost nečisté řešení.
Však já to nemyslel obecně (proto jsem psal "existují"). Ale vidím to tady na několika projektech - code base horko těžko vznikla v Pythonu*, už se to "seká", ale na přepis nebo dokonce identifikaci kritických částí autoři nemají čas a asi ani znalosti. Tady to můžeme řešit masivní paralelizací (běží teď 16 podů a klidně to jde naškálovat i víc), ale obecné řešení to samozřejmě není.
* dokonce byla snaha to nějak splichtit v BASHi, ale to by byl děs a hrůza (nebyl tam ani technický důvod, jen že lidi prostě BASH znali a Python ne)
V podstatě tuto mašinku:
https://insights-core-tutorials.readthedocs.io/en/latest/
Hlavně ta pravidla:
https://github.com/RedHatInsights/insights-core/blob/master/docs/notebooks/Diagnostic%20Walkthrough.ipynb
(ono to i trošku dává smysl, protože ta pravidla, resp. jejich náznak, tvoří admini, kteří ví, co způsobilo problém. A ti to většinou získávají z Bashí CLI)
Precetl jsem asi 20 tutorialu na korutiny v Pythonu, ale doted jsem to nepochopil. Tedy pochopil jsem ty tutorialy, ale mam pocit, ze vsechny jsou psane dost blbe pomoci prikladu s asyncio.sleep (nebo nejspis je to proste copy paste :) ), coz je sice pochopitelne - ted budu spat a jina korutina muze delat nejakou praci, nez se zase probudim a budu neco delat ja, ale uz nikde neni priklad, kdy misto asyncio.sleep je nejaka skutecne blokujici funkce (napriklad ten dlouho trvajici vypocet). Pokud neco takoveho pridam, tak vlastne uz vsechny korutiny bezi opet synchronne, abych dosahnul nejake konkurence, tak kazdou musim spustit ve zvlastnim threadu, takze vlastne uplne nerozumim tomu, k cemu je to dobre.
Jak píše Calculon - pokud se jedná o program, ve kterém je hodně I/O operací (třeba dotazy do DB, HTTP ve stylu dotaz-odpověď), tak se hodí použít korutiny (https://www.root.cz/clanky/soubezne-a-paralelne-bezici-ulohy-naprogramovane-v-pythonu-2/#k09). K tomu asi dodám tři věci:
1. ten asyncio.sleep je prostě to nejjednodušš, čím je možné simulovat práci. Ale stačí to nahradit třeba za ty HTTP dotazy (https://www.root.cz/clanky/soubezne-a-paralelne-bezici-ulohy-naprogramovane-v-pythonu-2/#k18)
2. Korutiny mají dost velké množství výhod. Třeba se vůbec nemusí řešit přístup ke stejným objektům - žádné pokusy o transakce, mutexy atd. Úlohy totiž běží souběžně, ale současně i kooperativně, takže vývojář ví (měl by vědět) co přesně dělá.
3. Je tady ještě sémantický důvod. Například generátor typu range se dá typicky vytvořit korutinou, stačí použít yield (bez asyncio), což mi připadá jako zdaleka nejčistší řešení.
re "abych dosahnul nejake konkurence" - nerad opravuji v diskuzi, ale concurrent je souběžnost a ne paralelnost. Já vím, ono se to někdy používá jako synonymum, ale právěže tomu tak vůbec není. Korutiny umožňují tvorbu souběžného kódu (klidně v jednom vláknu), ne nutně paralelně běžící - to je totiž vyšší level (za který programátor musí zaplatit).
No, ono tady je problém, že async IO nejsou korutiny. Async IO je jenom a pouze o tom, že plnotučné (kernelové) vlákno není blokováno IO. Takže můžete mít souběžně několik IO operací v jednom vláknu.
No a toto právě dalo smysl do té doby (resp. se synchronním IO) "nesmyslným" korutinám. Protože pokud je hodně IO operací (typicky networking), tak díky async IO (a přepnutí korutiny při IO, místo zablokování celého vlákna, dokud se IO nedokončí) se z korutin stávají (v podstatě) souběžně běžící vlákna (protože ty IO operace opravdu běží souběžně).
Mimochodem korutiny v async IO prostředí běžně běží paralelně (v threadpoolu).
Dnes uz neni moc velky rozdil mezi asyncio a temi jmenovanymi knihovnami, nova dokumentace k asyncio je celkem dobra, ale problem je, ze k asyncio existuje spousta zastaralych tutorialu.
Zejmena Curio ma peknou dokumentaci doplnenou Davidovymi prednaskami.
upresneni: ten predchozi komentar je muj z mobilniho uctu
23. 3. 2022, 18:22 editováno autorem komentáře
No právě. Pochopit to nemám problém, ale používat v Pythonu :D.
Třeba v .NETu F# -- no problem. Kde ale nemám zcela jasno,
je v jakých vrstvách to má a nemá smysl. V doménové zcela určitě ne.
V servisní/integrační tam zcela jistě jo, pak ale najít tu správnou míru.
24. 3. 2022, 08:25 editováno autorem komentáře
Jo promiň, to je slovník z Domain-Driven Design. V doménové vrstvě není žádné IO, jen čisté struktury a funkce (objekty, metody). Ale můžou tam být i zdlouhavé výpočty, pak by tam asynchronost měla smysl (třeba právě v tom kryptu? nevím). V praxi se to ale většinou tak neobjevuje. V servisní nebo integrační vrstvě, kde už se komunikuje se světem bych to využil. Ale zase pro jednoduchost, otevřu DB provedu příkaz a pokud to netrvá dlouho, tak radši programuju prostě blokujícím způsobem..
Python je fajn jazyk, ale na niektoré veci sa nehodí; trebárs na prácu s dátumami a časom či na konkurentné programovanie. Existuje tam veľa bugov a celé API je vo vývoji. Napr. populárny requests či Flask nepodporujú asynchrónne rutiny. Naozaj je jednoduchšie zvoliť si vhodnejší jazyk/platformu ako je F#, Go, Clojure, Groovy, Haskell či Erlang. (Fakt nechápem ľudí, ktorí idú oveľa náročnejšou cestou Python/GIL/C knižnice). Možno tak o 5-10 rokov to bude iné.
Asynchrónne rutiny ale už vyzerajú celkom k svetu.
Kombinácia asyncio a httpx:
#!/usr/bin/python import httpx import asyncio async def get_async(url): async with httpx.AsyncClient() as client: return await client.get(url) urls = ['http://webcode.me', 'https://httpbin.org/get', 'https://google.com', 'https://stackoverflow.com', 'https://github.com'] async def launch(): resps = await asyncio.gather(*map(get_async, urls)) data = [resp.status_code for resp in resps] for status_code in data: print(status_code) asyncio.run(launch())
Ďalej tu máme vynikajúcu knižnicu Playwright; to je v podstate async
headless browser. Môžeme klikať, robiť screenshoty, vyplňovať
formuláre a pod.
#!/usr/bin/python import asyncio from playwright.async_api import async_playwright async def run(playwright): chromium = playwright.chromium # or "firefox" or "webkit". browser = await chromium.launch() page = await browser.new_page() await page.goto("http://webcode.me") title = await page.title() print(title) await browser.close() async def main(): async with async_playwright() as playwright: await run(playwright) asyncio.run(main())
Souhlas, situace neni idealni. Existuje nekolik implementaci asynchronnich requests a asynchronni webove frameworky, ale treba django plne asynchronni zatim neni. Vetsinou masivni asynchronnost u backendu postavenem nad sql stejne nevyuzijete, bottlneck je databaze.
24. 3. 2022, 02:03 editováno autorem komentáře
Protože ve standardní knihovně je to opravdu strašné, je tam hrozně moc typů a je to strašně rozlezlé. To vůbec nemluvím o časových pásmech, ale to se v posledních verzí hodně zlepšilo. Trochu mi to připomíná, jak to bylo v Java před verzí 8. Škoda, že tohle v Pythonu nedotáhnou, protože používat pro práci s datem externí knihovnu mi přijde divný.
Ako už bolo povedané, je to tam nesystematicky pomiešané v rôznych balíčkoch, plus si konkurujú viaceré externé knižnice. Ale ani jedna ani zďaleka nepostihuje dostatočne prácu s dátumami a časom.
Ide totiž o mimoriadne náročnú problematiku. Žiadna datetime knižnica nie je úplná. (Ono to je prakticky práca bez konca.)
Koľko je rôznych kalendárov! Niektoré krajiny mali alebo majú viaceré kalendáre...
Asi najviac prepracované to má standard JVM & Time4J. https://github.com/MenoData/Time4J
Ostatné platformy sú riadne pozadu. The right tool for the right job.
24. 3. 2022, 17:42 editováno autorem komentáře
A ešte nemôžem obísť F#. Najnovšia verzia vydaná teraz na jeseň
umožňuje elegantnú integráciu s .NET taskami.
open System.Net.Http open System.Text.RegularExpressions open System.Threading.Tasks let fetchTitleAsync (url: string) = task { use client = new HttpClient() let! html = client.GetStringAsync(url) let pattern = "<title>\s*(.+?)\s*</title>" let m = Regex.Match(html, pattern) return m.Value } let sites = [| "http://webcode.me" "http://example.com" "https://bing.com" "http://httpbin.org" "https://ifconfig.me" "http://termbin.com" "https://github.com" |] let titles = sites |> Array.map fetchTitleAsync |> Task.WhenAll |> Async.AwaitTask |> Async.RunSynchronously titles |> Array.iter (fun title -> printfn $"%s{title}")
Async kód, computation expressions & custom DSL.
Príklad asynchrónne zadá do vyhľadávača heslo, klikne na selektovaný odkaz,
počká si na odpoveď a spraví screenshot. Plus si to všetko zabalíme do
elegantného DSLka.
Dokáže nejaký iný jazyk tomuto konkurovať?
#r "nuget: Microsoft.Playwright" open Microsoft.Playwright open System.Threading.Tasks type PlaywrightBuilder() = member _.Yield _ = task { let! pw = Playwright.CreateAsync() let! browser = pw.Firefox.LaunchAsync(BrowserTypeLaunchOptions(Headless = true)) return! browser.NewPageAsync() } [<CustomOperation "visit">] member _.Visit(page: Task<IPage>, url) = task { let! page = page let! _ = page.GotoAsync(url) return page } [<CustomOperation "screenshot">] member _.Screenshot(page: Task<IPage>, name) = task { let! page = page let! _ = page.ScreenshotAsync(PageScreenshotOptions(Path = $"{name}.png")) return page } [<CustomOperation "write">] member _.Write(page: Task<IPage>, selector, value) = task { let! page = page let! _ = page.FillAsync(selector, value) return page } [<CustomOperation "click">] member _.Click(page: Task<IPage>, selector) = task { let! page = page let! _ = page.ClickAsync(selector) return page } [<CustomOperation "wait">] member _.Wait(page: Task<IPage>, seconds) = task { let! page = page let! _ = page.WaitForTimeoutAsync(seconds) return page } [<CustomOperation "waitFor">] member _.WaitFor(page: Task<IPage>, selector) = task { let! page = page let! _ = page.WaitForSelectorAsync(selector) return page } let playwright = PlaywrightBuilder() playwright { visit "https://duckduckgo.com/" write "input" "root.cz" click "input[type='submit']" click "text=/Root\.cz/" waitFor "text=Root.cz - informace nejen ze světa Linuxu" screenshot "root" } |> Async.AwaitTask |> Async.RunSynchronously
красота
"Dokáže nejaký iný jazyk tomuto konkurovať?"
Jasně dokáže, třeba Scala, která má lepší typový systém a dokonce je pod kapotou i jednodušší než F#. Problém F# je že to jsou vlastně dva jazyky slepené do jednoho. .NET runtime je objektový a tohle stále do F# někde probublává. Ale jinak žádná, je to na míle lepší než Python :D
To je na mě? Sorry, nevidím tu dobře odsazení. Jestli jo, tak například Agda (je to popsané v knize Verified functional programming in Agda). V té knize je odkaz na Cayenne (tento jazyk neznám, ale údajně to tam jde taky). Já si to cvičně napsal v Idrisu, aniž bych znal tu implementaci z výše uvedené knihy, ono to jde napsat v tomto typu jazyků jen jedním způsobem. Je to hezké cvičení ze silných typových systémů. Možná (snad) se tady tomu bude někdy věnovat kolega Tišnovský :)
Díky. Tohle chování je díky závislostním typům? Pokud ano, tak by to měla Scala 3 také zvládnout myslím. Jen mně teď v tom konkrétním případě nenapadá k čemu bych to využil. V tom tvém případě vrací funkci, já ale interpolaci vždy používám tak, že tam narvu známé argumenty a vracím hodnotu. Nebo mi něco uniká.
Ano, používají se záv. typy. Příklad použití je třeba (format “Error at line %d: %s”) line msg
s tím, že již během typové kontroly se kontrolují typy obou proměnných v závislosti na formátovacím řetězci. To v závorce je ta funkce zavolaná s dvěma argumenty, dostanu tedy řetězec. Stejně jako v C, jen holt je to celé typové bezpečné. Já tohle beru jako cvičení, ale praktické použití to IMHO má, na rozdíl od některých jiných příkladů :)
Tady je ten článek o Cayenne s příkladem typově bezpečného formátování: http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=B4FF3E0F00535ACBCDF4FED1ADE5499F?doi=10.1.1.47.155&rep=rep1&type=pdf
@all
Mal som na mysli reálne, nie na papieri. :)
Teoreticky môžu konkurovať JS/TS, Go, Python, C#. Žiadny iný jazyk nemá knižnicu pre headless browsing. JVM jazyky majú, ale nepodporuje asynchrónne programovanie.
Tipoval by som, že najbližšie k tomu má Clojure. Zatiaľ do Clojure len fušujem, ale viem, že DSLko dokáže spraviť, predpokladám, že aj ekvivalent computational expressions. Ale žiaľ nemá podporu pre async Playwright.
(Add OOP. Scala nevie vypísať hello world bez toho, aby sme funkciu museli vopchať do objektu.)
To není pravda. Scala 3 má na míle lepší typový systém než F# a hello world taky zvládne.https://docs.scala-lang.org/scala3/book/taste-hello-world.html Nějaký další problém?
https://www.scala-lang.org/blog/2016/02/03/essence-of-scala.html
27. 3. 2022, 09:58 editováno autorem komentáře
OK. Netušil som, že od Scala 3 je možné pomocou @main anotácie. + pre Scalu.
Lež tu sme ušli od pôvodnej rečníckej otázky. Tá sa týkala async workflows/kooperatívnych async rutín a DSL v jednoduchom, elegantnom programe. Nie typového systému.
(Ináč netuším prečo, ale tu na roote sa často diskusia zvŕtne na datové typy.)
DSL a async se ve Scale řeší taky pěkně. Ale nic proti F#. To proč nemá takový typový systém je by-design. Ale co v něm je implementováno, je řešeno velmi pěkně. Bohužel trpí díky MS a jeho pověsti.
https://www.reddit.com/r/fsharp/comments/pkz66r/don_syme_talks_about_downsides_of_type_classes/
30. 3. 2022, 17:06 editováno autorem komentáře
Zdá sa mi, že Python sa nechal dosť inšpirovať Javou vo svojom API.
Toto je Groovy kód:
import java.util.concurrent.Executors import java.util.concurrent.TimeUnit import java.net.http.HttpClient import java.net.http.HttpRequest import java.net.http.HttpResponse int nThreads = 30 def executor = Executors.newFixedThreadPool(nThreads) def urls = [ "https://crunchify.com", "https://yahoo.com", "https://www.ebay.com", "https://google.com", "https://www.example.co", "https://paypal.com", "http://bing.com/", "https://techcrunch.com/", "http://mashable.com/", "https://pro.crunchify.com/", "https://wordpress.com/", "https://wordpress.org/", "https://example.com/", "https://sjsu.edu/", "https://ask.crunchify.com/", "https://test.com.au/", "https://www.wikipedia.org/", "https://en.wikipedia.org" ] for (String url in urls ) { executor.execute(() -> { worker(url) // try { // worker(url) // } catch (Exception e) { // e.printStackTrace() // } }) } executor.shutdown() executor.awaitTermination(30, TimeUnit.SECONDS) println("finished") def worker(url) { def client = HttpClient.newHttpClient() def request = HttpRequest.newBuilder() .uri(URI.create(url)) .build() HttpResponse<Void> res = client.send(request, HttpResponse.BodyHandlers.discarding()) println "${url}: ${res.statusCode()}" }
Zaujímavé je tiež, že kód môže byť asynchrónny a zároveň bežať vo viacerých vláknach. To je už potom iný bolehlav.
Minule v diskusii sa ktosi pýtal, načo je dobrý threading. Nemám po ruke Python kód, tak použijem Groovy.
GUI toolkity sú všetky jednovláknové. To znamená, že každý event handler sa musí čo najrýchlejšie ukončiť, inak aplikácia mrzne a komponenty sa neprekresľujú. A práve tam sa používa threading. Napr Swing má nato SwingWorker, ktorý nám zjednodušuje vytvorenie samostatného vlákna vrámci aplikácie.
Príklad začne vyhľadávať obrázky na disku a nájdené súbory priebežne zapisuje to okna. Celé to vyhľadávanie sa deje v rámi samostatného vlákna.
import java.awt.Container import java.awt.EventQueue import java.awt.event.ActionEvent import java.io.IOException import java.nio.file.FileSystems import java.nio.file.FileVisitResult import java.nio.file.FileVisitor import java.nio.file.Files import java.nio.file.Path import java.nio.file.PathMatcher import java.nio.file.Paths import java.nio.file.attribute.BasicFileAttributes import java.util.List import javax.swing.AbstractAction import javax.swing.GroupLayout import static javax.swing.GroupLayout.Alignment.BASELINE import static javax.swing.GroupLayout.Alignment.CENTER import javax.swing.JButton import javax.swing.JComponent import javax.swing.JFrame import javax.swing.JLabel import javax.swing.JScrollPane import javax.swing.JTextArea import javax.swing.SwingWorker /* * Advanced Java Swing * * This program initiates a background search for * various image files in a user's home directory. */ class SearchingImages extends JFrame { private JTextArea area private JLabel lbl private JButton btn public SearchingImages() { initUI() } private void initUI() { area = new JTextArea(20, 40) area.setEditable(false) var spane = new JScrollPane(area) btn = new JButton("Start") btn.addActionListener(new StartSearchAction()) lbl = new JLabel("Files found: ") createLayout(spane, btn, lbl) setTitle("Searching for files") setLocationRelativeTo(null) setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) } private void createLayout(JComponent... arg) { Container pane = getContentPane() def gl = new GroupLayout(pane) pane.setLayout(gl) gl.setAutoCreateContainerGaps(true) gl.setAutoCreateGaps(true) gl.setHorizontalGroup(gl.createParallelGroup(CENTER) .addComponent(arg[0]) .addGroup(gl.createSequentialGroup() .addComponent(arg[1]) .addComponent(arg[2])) ) gl.setVerticalGroup(gl.createSequentialGroup() .addComponent(arg[0]) .addGroup(gl.createParallelGroup(BASELINE) .addComponent(arg[1]) .addComponent(arg[2])) ) pack() } private class StartSearchAction extends AbstractAction { @Override void actionPerformed(ActionEvent e) { doStartSearch() } private void doStartSearch() { btn.setEnabled(false) def tw = new FileTreeWalker() tw.execute() } } static void main(String... args) { EventQueue.invokeLater(() -> { def ex = new SearchingImages() ex.setVisible(true) }) } private class FileTreeWalker extends SwingWorker<Void, Path> implements FileVisitor<Path> { private final PathMatcher matcher private int count = 0 public FileTreeWalker() { def str = "glob:**.{png,PNG,gif,GIF,jpg,jpeg,JPG,JPEG}" matcher = FileSystems.getDefault().getPathMatcher(str) } @Override protected Void doInBackground() throws IOException { // Path p = Paths.get(System.getProperty("user.home")) Path p = Paths.get("C:/Users/Jano/Documents") Files.walkFileTree(p, this) return null } @Override protected void process(List<Path> chunks) { for (Path p in chunks) { area.append("${p.toString()}\n") count++ lbl.setText("Files found: ${count}")) } } @Override protected void done() { btn.setEnabled(true) } @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { return FileVisitResult.CONTINUE } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (matcher.matches(file)) { publish(file) } return FileVisitResult.CONTINUE } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) { return FileVisitResult.TERMINATE } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) { return FileVisitResult.CONTINUE } } }
Knižnica Playwright žiaľ nepodporuje async kód pre JVM.
There are no plans to add async API in java (lack of async/awai makes it really cumbersome to write async code like we do in typescript).
@Grab(group='com.microsoft.playwright', module='playwright', version='1.19.0') import com.microsoft.playwright.Playwright Playwright.create().withCloseable { client -> def browser = client.chromium().launch() def page = browser.newPage() page.navigate("http://webcode.me") println page.title() }
Děkuju za uvedení tříd ThreadPoolExecutor a ProcessPoolExecutor - ani jednu jsem neznal a je to docela pěkný mechanismus.
K asyncio bych měl jednu prosbu do dalších dílů - bylo by možné zkusit popsat to, jak fungují výjimky a obecně ukončování programů, které s asyncio na něco čekají? Asi to popisuju dost nešikovně, ale jde o konkrétní problém - před časem jsem psal pythoní "server" co na jedné straně byl připojený na frekvenční měnič přes modbusTCP a na druhé straně přes aiohttp a socketio nabízel web, ze kterého se ten měnič dal ovládat. Celé jsem to dohromady poplácal celkem snadno, ale problém nastal když nějaká část spadla na výjimce. Pak se to chovalo dost divně, ta část programu kde to spadlo pak umřela ale ostatní "tasky" běžely dál. A podle googlu to je věc, že kterou jsem "problém" neměl sám...