0

I am building an RSS Reader and I want to add a periodic task that will check for new feed items. If it finds any new items, it will update the Live Tile of the app accordingly.

The problem that I encounter is that I am using the DownloadStringAsync() method to download the feeds and check if they contain new items. So, sometimes the downloading process may take longer than 20 seconds (the time that a periodic task is given in order to complete its actions).

All I want is to ensure that the NotifyComplete() method will be called before the agent gets terminated by the OS, after 20 seconds of action. For this reason, I want to register a dispatcher timer with an interval of 15 seconds, that will call the NotifyComplete() method in its tick event.

However, I tried to declare and use the dispatcher timer, and an invalid cross-thread access error was raised. My Periodic Task code includes the following:

public class ScheduledAgent : ScheduledTaskAgent
{  
    //Register a DispatcherTimer
    DispatcherTimer masterTimer = new DispatcherTimer();

    private static volatile bool _classInitialized;

    public ScheduledAgent()
    {
        if (!_classInitialized)
        {
            _classInitialized = true;
            // Subscribe to the managed exception handler
            Deployment.Current.Dispatcher.BeginInvoke(delegate
            {
                Application.Current.UnhandledException += ScheduledAgent_UnhandledException;
            });
        }

        //Set Timer properties
        masterTimer.Interval = TimeSpan.FromSeconds(15);
        masterTimer.Tick += masterTimer_Tick;
    }

    protected override void OnInvoke(ScheduledTask task)
    {
        //TODO: Add code to perform your task in background
        masterTimer.Start();

        //Call DownloadStringAsync() and perform other tasks...
        //Call NotifyComplete() after the download is complete.
        //
    }


    private void masterTimer_Tick(object sender, EventArgs e)
    {
        masterTimer.Stop();
        //There is no more time left, we must call NotifyComplete() so as to avoid
        //having the periodic task terminated by the OS
        NotifyComplete();
    }
}

The question is, why this is happening and how I can resolve the issue. Thank you in advance!

Icarus
  • 139
  • 2
  • 13
  • Cross-thread issue aside, why are you trying to use a `DispatcherTimer` to `NotifyComplete()` early? that doesn't ensure your `ScheduledTaskAgent` will be called in future - no exceptions in the agent and the user continuing to use the app, will. – Neil Turner Jul 19 '13 at 16:39
  • There is not need for a Timer (DispatcherTimer or regular Timer). The time limit for background agents is in code execution time (ie: amount of machine cycles your code uses). Time to wait for a service to respond is not included in this time. – Shawn Kendrot Jul 19 '13 at 18:54
  • @ShawnKendrot That's a very interesting piece of information. Do you have any source to back it up? – Kevin Gosse Jul 20 '13 at 07:58
  • NeilTurner, thanks for pointing that out! Finally I don't need a `DispatcherTimer` at all. @ShawnKendrot So you suggest that whether `DownloadStringAsync()` returns after 2 or 50 seconds, the background agent will wait for it, and won't get abruptly terminated by the OS, right? – Icarus Jul 20 '13 at 17:25

1 Answers1

0

cross-thread access error is raised when you try to chage UI Property from a thread other than the one that created the control.

To pass it you use the Invoke method that exist in the control

the code should look something like this:

Control.Invoke((MethodInvoker)delegate{
//Do your work here for example NotifyComplete();
});
Swift
  • 1,861
  • 14
  • 17