Nejprve – omlouvám všem fanouškům Jacka Reachera, tento článek není o jedné z knih této série, leč jeho název ji obsahuje rovnou dvakrát 🙂 .
V mé poslední vydané Windows 10 aplikaci Event Countdowns jsem udělal nešťastnou chybu. Při registraci Background Tasku který měl aktualizovat dlaždice aplikace každých 30 minut jsem použil následující kód:
string myTaskName = "TileUpdaterBackgroundTask"; // check if task is already registered var task = BackgroundTaskRegistration.AllTasks.Where( cur => cur.Value.Name == myTaskName ).Select( c => c.Value ).SingleOrDefault(); if ( task != null ) { //do not register again return; } var backgroundAccess = await BackgroundExecutionManager.RequestAccessAsync(); if ( backgroundAccess == BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity || backgroundAccess == BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity ) { // register a new task BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder { Name = myTaskName, TaskEntryPoint = "TileUpdateTask.TileUpdateBackgroundTask" }; taskBuilder.SetTrigger( new TimeTrigger( 30, true ) ); BackgroundTaskRegistration myFirstTask = taskBuilder.Register(); }
Na první pohled nic neobvyklého. Nebo – to jsem si alespoň myslel. Den po vydání aplikace jsem se podíval na připnutou dlaždici odpočítávající čas do premiéry filmu Captain America: Civil War a s velkým překvapením zjistil, že zobrazený zbývající čas je byl o den posunutý! Okamžitě jsem zkontroloval zdrojový kód a po několika minutách zběsilého debugování jsem objevil skryté zlo – druhý parametr konstruktoru třídy TimeTrigger.
taskBuilder.SetTrigger( new TimeTrigger( 30, true ) );
Druhý parametr, oneShot, určuje, zda task bude spuštěn pouze jednou (hodnota true) nebo periodicky (hodnota false).
Moje naivní řešení tedy spočívalo ve výměně true za false a protože na počítači aplikace fungovala bez problémů, publikoval jsem aktualizovanou verzi na Store.
Když nová verze aplikace dorazila na můj telefon, s radostí jsem ji nainstaloval, spustil a čekal, až dlaždice znovu oživnou. A čekal jsem. A čekal jsem. A… nic.
Byl jsem zmaten a nechápal jsem, kde může být rozdíl mezi počítačem a telefonem. Tak jsem se znovu vrátil ke zdrojovému kódu a znovu jej promyslel. A pak – jsem to uviděl.
// check if task is already registered var task = BackgroundTaskRegistration.AllTasks.Where( cur => cur.Value.Name == myTaskName ).Select( c => c.Value ).SingleOrDefault(); if ( task != null ) { //do not register again return; }
Přirozeně jsem předpokládal, že jakmile oneShot Background Task je jednou spuštěn, systém jej automaticky odregistruje. Ve skutečnosti tomu tak ale není.
I poté co oneShot trigger spustí Background Task, task stejně zůstane zaregistrován!
To znamená, že po instalaci aktualizované verze aplikace na můj telefon a jejím spuštění se při pokusu o registraci tasku kód zastavil na kontrole podmínky task != null která se vyhodnotila jako true, protože task byl stále zaregistrován, přestože již proběhl!
Finální řešení tedy vyžadovalo vynutit odregistrování Background Tasku a jeho znovuzaregistrování s oneShot nastaveným na false.
Bug je odchycen a dlaždice znovu žijí!