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í!