Saving data before exiting in PeriodicTask
As the documentation says, OS provides you with merely [B]25 sec[/B] to complete your work on [I]PeriodicTask [/I]launch.
I have a long list of commands to be sent to the server in the background. So how do i make sure to save back the unsent stuff back to IsolatedStorage before my [B]25 sec[/B] gets over. Do i get terminating/finishing or some similar notification?
And while searching for this i came across [URL="http://stackoverflow.com/questions/14414947/scheduledactionservice-launchfortest-not-calling-scheduledtaskagents-oninvoke-a"]this[/URL]. Which says if [I]NotifyComplete()[/I] is not called in the [I]OnInvoke()[/I] i may face problems for subsequent [I]PeriodicTask [/I]launches. So how do i make sure to call [I]NotifyComplete()[/I] every time.
Regards
Re: Saving data before exiting in PeriodicTask
"Make sure to save back the unsent stuff" is something what can not be done in a reliable way. However you can certainly do exactly the opposite: send whatever you can, and only remove the stuff then, perhaps waiting for some acknowledgement. You may end up sending some commands multiple time so having some unique identifier for them is probably a good idea. Then the receiving party can discard doubles, but re-send the acknowledgement so the command will disappear from the queue.
For the 25 seconds you should simply measure it. You certainly have a loop if you are handling a list. Store a timestamp at the beginning, and bail out from the loop if more than -say- 23 seconds have passed.
Re: Saving data before exiting in PeriodicTask
Hi wizard_hu_, thanks for your response. And yes i thought about this approach but 25s is very small time and writing to isolated storage is a slow process, after all its writing to a file. So writing to isolated storage every time i get a response will waste few seconds from those 25 sec every time. So i was thinking if i load all commands in memory, send as much as i can in 25 sec and write back only once the remaining commands will help in utilizing those 25 sec more efficiently. That's why i was wondering if i can get some kind of 25 sec finishing notification.
Please correct me if i am mistaken.
Regards
Re: Saving data before exiting in PeriodicTask
[QUOTE=wizard_hu_;911361]For the 25 seconds you should simply measure it. You certainly have a loop if you are handling a list. Store a timestamp at the beginning, and bail out from the loop if more than -say- 23 seconds have passed.[/QUOTE]
Yes i have a unique ID associated with every command and i wait for the acknowledgement before sending next command but i am not too much aware with c#. I will be glad if you can explain on this with some code.
Re: Saving data before exiting in PeriodicTask
I really doubt that there would be any extra notification, but I actually do not know for sure.
Since you have unique ID-s, and thus the server can filter out duplicate commands, there is a lot of space for experimentation. Like you can collect the acknowledgements, and delay the file operation for the last few seconds, or schedule a couple write-back operations, for every 5 seconds for example. There will be duplicates remaining but the server can recognize them.
Also note that seconds are a short time for you to write megabytes of data on a piece of paper, but phones are a lot faster, you can actually create some benchmarking code (or just look up one on the Internet) if you want to see how much.
Re: Saving data before exiting in PeriodicTask
[QUOTE=wizard_hu_;911387]Like you can collect the acknowledgements, and delay the file operation for the last few seconds[/QUOTE]
That's the question. How do i achieve this? How do i know i have last few seconds remaining? Do OS notifies me? if yes how? if no, shall i run my own timer and what's the best way to run a timer C#?
Re: Saving data before exiting in PeriodicTask
[QUOTE=vinayppatil;911388]That's the question. How do i achieve this? How do i know i have last few seconds remaining? Do OS notifies me? if yes how? if no, shall i run my own timer and what's the best way to run a timer C#?[/QUOTE]
As Wizard_hu_ stated before, you need to store the timespan on the beginning of your OnInvoke method,
[CODE]DateTime onInvokeStart = DateTime.Now;
while((DateTime.Now-onInvokeStart).TotalSeconds <= 23) // DateTime.Now-onInvokeStart will return a TimeSpan type
{
// do you work
}
NotifyComplete();
[/CODE]
Re: Saving data before exiting in PeriodicTask
Hi Loukt, thanksfor your response. Used the same logic but implemented using Timer instead.
[QUOTE]Timer stopWorkTimer;
protected override void OnInvoke(ScheduledTask task)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
stopWorkTimer = new Timer(stopWorkTimer_Tick, null, TimeSpan.FromSeconds(20), TimeSpan.FromMilliseconds(-1));
});
//Send commands here
}
private void stopWorkTimer_Tick(object state)
{
//Save back remaining commands here
NotifyComplete();
}[/QUOTE]
Do let me know if anything wrong with this implementation.
Regards.
Re: Saving data before exiting in PeriodicTask
In its current form this piece of code idles for 23 seconds, then calls stopWorkTimer_Tick. It can be useful, but it can be used in a rather different way than Loukt's code snippet.
Re: Saving data before exiting in PeriodicTask
Hi wizard_hu. Sorry for the wrong code which seemed to sit idle for 23 sec. I modified my solution, Please check that out.
Regards.
Re: Saving data before exiting in PeriodicTask
To my understanding at least, Dispatcher can not invoke stopWorkTimer_Tick as long as something else is actively running. So the viability of this code depends on "Send commands here". If that operates with asynchronous calls, the Dispatcher will probably get the opportunity to call stopWorkTimer_Tick.
Re: Saving data before exiting in PeriodicTask
I've also faced the same questions on a recent project.
Using ResourceIntensiveTask was not an option for me because it requires the device to be plugged to a power source and working over Wifi.
What I did to use a local storage as a queue and then keep a state for each information I wanted to send to the server. For example, instead of building an collection in memory to send to the server, I would add new items to a local storage table in a FIFO (first in first out) list. Then what I do is to take one item from the list, send it to the server, get the response it got there, and delete locally. At the same time when sending to the server I send the unique local ID that is compared on the server to make sure its not a double entry. If it is, I dont raise an error, I just update the existent record and revert back to the client saying it got processed. And the app deletes the record from the local storage. In my case I decided to implement the "sync" process in a way that the device wins when resolving conflicts. You may have other needs.
I do this for each item.
What this does is to give me the absolute certain that even if the phone runs out of power at the middle of the process or that the user disconnects the phone, or if my app gets terminated by the OS due to memory and time restrictions, I will be able to resume the work later at the exact spot where I left it.
Its probably not the fastest solution but the it works. I also did this because sometimes the services take much more time to reply than we expect and this is a way to keep my data safe. For example, if you are working on 2G, 3G, LTE or even WIFI you can get a huge difference in response times. The time that takes to upload the same amount of data when on 2G or even 3G compared to LTE can be substantial
My 2 cents
EDIT: To check when you have to call NotifyComplete and cancel the work being done you can use a timer for 20 seconds for example, to ensure you have enough time to exit with success.
Re: Saving data before exiting in PeriodicTask
[QUOTE=wizard_hu_;911478]To my understanding at least, Dispatcher can not invoke stopWorkTimer_Tick as long as something else is actively running. So the viability of this code depends on "Send commands here". If that operates with asynchronous calls, the Dispatcher will probably get the opportunity to call stopWorkTimer_Tick.[/QUOTE]
I didn't knew that. How about [B]Timer[/B]. Does it has the same behavior.?
Re: Saving data before exiting in PeriodicTask
Hi João. Thanks for the detailed description. My implementation is same in all aspect to yours except "i load all commands at time in memory and save the remaining once back while exiting the app". Actually i did not thought of the fact that app can also exit in scenarios where in i wont have opportunity to save unsent stuff.:P So thanks a lot for pointing that out. Will change my implementation to take care of it.
Regards
Re: Saving data before exiting in PeriodicTask
Vinay is planning on writing an article to capture this - thanks! Any advice on best name for such an article?
Ideally we'd cover that this is about having more data to send than allowed by a single periodic task. More generally its about ensuring that any operation that can't complete in a single task can be resumed without data loss.
Some ideas:
* [B]Saving data before periodic task gets terminated in Windows Phone[/B] - covers that we're worried about termination but not why we need to save data
* [B]Sending data safely in a Windows Phone periodic task[/B] - covers that sending data during a periodic task is something that needs to be done with care, but not why
* [B]Safe data transmission in a Windows Phone periodic task[/B]
* [B]How to transmit large amounts of data in a Windows Phone periodic task[/B] - large amounts of data doesn't capture all of the other reasons we might not be able to send -e .g. slow connection
* [B]Handing potentially long running periodic tasks on Windows Phone[/B]
I like the last one best ([B]Handing potentially long running periodic tasks on Windows Phone[/B]) because it captures that there are a lot of things that can cause a task to go over time and even a very small action relying on network could take ages. It also allows us to capture the importance of making sure we call NotifyComplete in time, and how to do that. It doesn't capture this use case of "sending data", but I think we could still cover that in the article as the "example" of a long running task.
Anyone got a better title?
Regards
H