Background task is starting unreliably - c#

I have an UWP app that is dependant on a background task. This task should thus be running all the time when the user is using the device. I have tried registering it with these triggers:
ApplicationTrigger _AppTrigger = new ApplicationTrigger();
builderInApp.SetTrigger(_AppTrigger);
builderSession.SetTrigger(new SystemTrigger(SystemTriggerType.SessionConnected, false));
builderPower.SetTrigger(new SystemTrigger(SystemTriggerType.PowerStateChange, false));
But it seems like sometimes the task does not start. It starts 90% of the time after a restart or shutdown, continues 100% of the time after energy-saving mode, works 100% of the time if the system is just idle, about 50% after a Hybernation and only rarely if I do Energy Saver and then hybernate without unlocking.
Is there something I can do to make this more reliable? I have already added <rescap:Capability Name="extendedBackgroundTaskTime"/> and enabled user management by User instead of windows.
Should I add some more triggers? Which ones? Is there another way to get better reliability? I don't mind using a .Net component if that would help, but my background task does have to be UWP.
Other question I have about this:
If I have triggered the background with trigger a, and trigger a fires again, does the process launch a second time, get cancelled and relaunched, or nothing happens?
Same question if I have triggered the background with trigger a, and trigger b fires, does the process launch a second time, get cancelled and relaunched, or nothing happens?
Edit: I have tried using StartupTask, but cannot get it to trigger after hybernation.

Related

Windows Hello Unlock Companion Device Framework Background Task Not Being Triggered

I have been testing a C# Companion Device Framework application, which unlocks my laptop fine for the most part. However, it doesn't seem to work after I leave my laptop locked for a while.
I used the code from the CDF GitHub sample to fire a toast notification when the background task for my UWP companion app is triggered.
This shows me that there is never an issue when I attempt an unlock shortly after locking the machine. When I lock my machine, I immediately see the toast notification indicating that the background task was triggered. However, if I lock my laptop and leave it for a few minutes, it doesn't appear that the background task gets triggered again, even though I wake up the screen and press buttons.
I want my CDF app to always be able to unlock my machine. What did I do wrong? Hopefully I don't need it, but is there a workaround like registering a second trigger for the background task to a custom service?
UPDATE: It appears this occurs only if the computer does not go to sleep, which may occur in the case that someone has either set a long time before sleep or has sleep off completely (as I did previously). If the laptop does go to sleep, and has to be woken up with a trackpad click, then the background task seems to fire.
The problem is, Windows UWP stops to fire the event WaitForUserConfirmation after awhile.
At present, we have 2 possible solutions:
user hits the keyboard and the background task catches the event CollectingCredential and invokes the companion device authentication
once the background task is running, it loops until the event CredentialAuthenticated, and it runs the companion device authentication periodically.

How do you prevent BackgroundTask from being cancelled if it's appears Idle (but is not due to very small regular workload)?

I have an app that uses a timer similar to this example code:
Sample Code for BackgroundTasks
Specifically the part with a timer.
So my code runs as intended when I launch the app in debugger. Every minute the event fires and I log to a text file (and do a tile notification).
My problem is when I run it normally without debugging, it runs four times (sometimes five) and then nothing. Looking at the processes running I can see the backgroundtask and then its gone. I've got logging in the OnCancelled even and it's never called.
I even tried creating a deconstructor for the background task to see if that is called (and put some logging there) and it doesn't seem to be.
Also no exceptions seem to be thrown, at least they are not logged and I have a try catch around the timer.
Suggestions on how I can track down why the background task seems to be squashed (I thought if the system wants them closed, it cancels them?)
Update: I ran the app normally without debugger attached, and when I saw the backgroundtask process appear, I attached my debugger to it. It ran for 8 minutes (where the log was showing previous runs stopped after four). When I detached the debugger at that point it ran a further four times (once per minute) and then the process disappeared.
Update: Ok I think I have worked out what is happening, but not why.
http://msdn.microsoft.com/en-au/library/windows/apps/hh974425.aspx
When you are not debugging, Windows Process Lifetime Management (PLM) controls the execution state of your app—starting, suspending, resuming, and terminating the app in response to user actions and the state of the device. When you are debugging, Windows disables these activation events.
So I guess this may change my question to how do I find out why Backgroundtask is being suspended when it still has work to do?
Update: Worked out my issue, I was attaching Canceled handler to a field variable (which was being assigned in Run method. Attaching Canceled handler directly to the instance passed into Run method made the Cancel call work. I didn't think that would make a difference as its a reference tot he same thing. Anyway, Cancel reason is "IdleTask". Increasing the frequency of the timer seems to make the background task not get cancelled.
So question is now How much is enough work to not be cancelled due to being Idle? Can you check for this and adjust? Can you override the check? I don't want to just do work for the sake of not appearing idle. That's going to waste battery life!
I have a similar problem (and found for my app an acceptable workaround).
But your question is interresting and still unanswered:
Although with a BackgroundTaskDeferral sometimes the system assume that the task is idle and cancel the task:
BackgroundTaskDeferral defferal = taskInstance.GetDeferral();
while (Task runtime less than 14 minutes and 35 seconds)
{
... do something
// wait 20 seconds
new System.Threading.ManualResetEvent(false).WaitOne(20000);
}
defferal.Complete();
The real task is a little bit more complicated:).
I also don't want to just do work for the sake of not appearing idle.

How to stop scheduledtask running when foreground app is active windows phone 8

I've posted previously about synchronisation issues with my background scheduled task having to access a SQLite DB and IsolatedStorge that the foreground app uses.
To simplify the process I thought about just preventing my background task from running altogther, it isn't imperative that it runs, especially when the foreground app is active.
Is there a way to do this?
I thought about using IsolatedStorage to set a flag when the app launches then remove it when it exits, then have the background task check the setting, protected by mutex.
I think the idea is fine in principle, but I guess there will be times when the flag isn't unset, for example if the battery dies... Which means potentially, after turning the phone on, if the user never uses the app and exits properly, the background task will never run. This might not be too much of an issue.
Is using some kind of flag like this the only way to achieve such functionality?
Thanks
There is an inter process communication mechanism to achieve this functionality.
As both the foreground app and scheduletask run as different processes, IPC could be used for it.
Please refer to Named Events.
In your OnInvoke Method subscribe for a named event which will be fired by your foreground app as soon as it is launched/resumed.
As soon as you get a signal via this event in background agent, just call NotifyComplete and you are done.

Mango fast app switching & heavy processing crash

I have a WP7 app that sometimes has to make a long (5-25 sec) processing.
With Mango, when the app is set to Dormant state while it was processing (ex: the user presses the Windows button or locks the screen), when the user comes back, the app crashes.
I tried on the emulator and on my device, same behavior.
If I reproduce it in debug mode on Visual Studio, it doesn't crash so it's hard to find what is really happening.
To reproduce it, start a new Windows Phone project, add a button on MainPage.xaml & add an event handler on the click event that executes an infinite loop:
while (true)
{
System.Threading.Thread.Sleep(100);
}
My question is: What is really happening? Why does it crash? Isn't fast app switching supposed to just pause the app process and resume it?
EDIT:
Another thing I noticed is that when running the heavy process, the deactivated & activated events do not seem to be raised when I get out/in the app.
Found the answer on the official Windows Phone forum (link). Here it is:
Why it crashes:
From the time the app is deactivated, it has exactly ten seconds to
finish up what it is doing. If the code takes more than ten seconds,
the OS will terminate the app.
Why the deactivated & activated events are not raised when I get out/in the app:
If the process is blocking the UI thread this also blocks the message
dispatch loop so I suspect that this is the reason why your app never
gets a chance to detect and handle the events.
Your problem is simple. WP7 cant really put your threads in a dormant state when you are under heavy processing in this fast time and will save a corrupt state. This state will crash when its reactivated.
It works in the debugger because the debugger makes everything slower and then WP7 has more time.
From Documentation:
When the user navigates forward, away from an application, after the Deactivated event is raised, the operating system will attempt to put the application into a dormant state. In this state, all of the application’s threads are stopped and no processing takes place, but the application remains intact in memory. If the application is reactivated from this state, the application does not need to re-create any state, because it has been preserved.
Source: http://msdn.microsoft.com/en-us/library/ff817008(v=vs.92).aspx

C# on .net Mobile Framework - Windows form property won't change

I'm writing a c# application that requires user authentication.
When the user hits the log in button, quite a bit of stuff is done in the background, but I'm having trouble informing the user that something is happening, and that the program isn't just frozen.
I have some hidden text fields that I would like to have show up after they log in, while this stuff is running, but I can't seem to get it to show up.
Basically, when the user hits the log in button, it checks to see if their credentials are correct, then the messages should show up, and then either some other functions might run, followed by a different form being shown.
After the credentials are checked, and I know that the user is valid, I tried running this:
please_wait.Visible = true;
But it doesn't change when it gets to that point in the code.
I've tried threading it, to see if that would help. Instead of calling the above line, I just start a thread that does it.
That doesn't work either. The field still doesn't show up.
If I return out of the function right after I either start the thread or change the Visible property, it works just fine.
How do I get it to work fine and have more code run after the change?
The problem isn't that you need to update the UI from a background thread. Rather, it's that you should be performing your long-running task in a background thread and marshalling updates to the foreground. This is frequently done via a BackgroundWorker with progress notification (on a progressbar, for example).
Basically, your UI foreground thread is either loaded or blocked doing work, so it isn't handling messages in its message queue to update your user interface.
Along with what Greg recommends (which is certainly the first step if you're not already doing it) you may also need to give up some quantum.
If you are taxing the scheduler, it's possible that the UI updates (which are pretty low priority) may be getting preempted until your worker is complete. Adding an Application.DoEvents (or maybe Thread.Sleep(1) in the background thread) could give the UI a little scheduler time to paint.
Have you tried adding a call to Application.DoEvents()? It's a hack, but it's all you sometimes need.

Categories

Resources