后台任务跳过计划,有时每 60 分钟更新一次

发布于 2024-12-21 17:08:43 字数 14568 浏览 1 评论 0原文

我很快就会失去它......我有两个具有工作后台任务的应用程序正在更新活动磁贴。下载、解析动态磁贴的数据,然后动态创建图像并用作动态磁贴的背景。

一两天内一切正常,但随后更新开始表现得非常奇怪。前一两天,我的应用程序的两个动态磁贴都像发条一样每 28 分钟更新一次。但随后他们开始跳过更新。通常,当应用程序 B 不更新活动磁贴时,应用程序 A 就会更新,因此它们不会同时更新,并且每小时只更新一次。简而言之,他们远远偏离了计划。

这真的很令人沮丧,因为我需要能够依赖每 30 分钟更新一次的图块(如果我有足够的电池、良好的接收效果等等)。

如果有人可以帮助我,或者看看我的代码,看看是否有什么东西扰乱了更新间隔(比如没有正确调用 NotifyComplete),我将非常感激。我删除了一些代码并尝试简化它。请询问您是否还需要其他信息来理解这一点。

在过去的两个月里,我一直在尝试解决这个问题,尝试不同的手机并非常仔细地检查我的代码。

我们比您想象的更感激您的帮助。 提前致谢。

My OnInvoke function:

        Timer t = null;

        ShellToast toast = new ShellToast();


        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(strUrlHBH));
            request.Accept = "*/*";
            request.AllowAutoRedirect = true;

            // disable caching.
            request.Headers["Cache-Control"] = "no-cache";
            request.Headers["Pragma"] = "no-cache";

            t = new Timer(
                state =>
                {
                    if (string.Compare(state.ToString(), id, StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        //logger.Write("Timeout reached for connection [{0}], aborting download.", id);
                        runNotifyComplete = false;
                        NotifyComplete();
                        request.Abort();
                        t.Dispose();
                    }

                },
                id,
                timeout,
                0);

            request.BeginGetResponse(
                r =>
                {
                    try
                    {
                        if (t != null)
                        {
                            t.Dispose();
                        }

                        var httpRequest = (HttpWebRequest)r.AsyncState;
                        var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);
                        using (var reader = new StreamReader(httpResponse.GetResponseStream()))
                        {

                            var response = reader.ReadToEnd();

                            Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                try
                                {

                                    //Parse the result

                                    if (boolResult) //If we have a result
                                    {


                                        Grid grid = new Grid();



                                        StackPanel sp = new StackPanel();
                                        sp.Height = 173;
                                        sp.Width = 173;



                                        //StreamResourceInfo info = Application.GetResourceStream(new Uri("Pin-to-start2.png", UriKind.Relative));


                                        if ((bool)settings["LiveTileMetro"] == true)
                                        {

                                            // create source bitmap for Image control (image is assumed to be alread 173x173)
                                            /*WriteableBitmap wbmp2 = new WriteableBitmap(1, 1);
                                            wbmp2.SetSource(info.Stream);
                                            Image img = new Image();
                                            img.Source = wbmp2;
                                            // add Image to Grid
                                            grid.Children.Add(img);
                                            strBackBackground = "Pin-to-start2.png";
                                        }
                                        else
                                        {*/
                                            sp.Background = (SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"];
                                            //sp.Background.Opacity = 0.0;
                                            strBackBackground = "";
                                        }

                                        StreamResourceInfo info;

                                        //GC.Collect();
                                        info = Application.GetResourceStream(new Uri("/MyApp;component/images/Icons/livetile/livetile.png", UriKind.Relative));


                                        WriteableBitmap wbmp3 = new WriteableBitmap(1, 1);
                                        try
                                        {
                                            wbmp3.SetSource(info.Stream);
                                        }
                                        catch
                                        {
                                        }
                                        Image img3 = new Image();
                                        img3.Source = wbmp3;
                                        // add Image to Grid
                                        img3.Width = 173;
                                        img3.Height = 173;
                                        img3.Margin = new Thickness { Left = 0, Bottom = 0, Right = 0, Top = 0 };


                                        TextBlock txtTemperature = new TextBlock();
                                        TextBlock txtTemperatureRing = new TextBlock();

                                        txtTemperature.Foreground = new SolidColorBrush(Colors.White);
                                        txtTemperature.Text = strTemp;
                                        txtTemperature.TextAlignment = TextAlignment.Right;
                                        txtTemperatureRing.Style = (Style)Application.Current.Resources["PhoneTextTitle3Style"];
                                        txtTemperatureRing.FontFamily = new FontFamily("Segoe WP Light");
                                        txtTemperatureRing.FontSize = 40;
                                        txtTemperatureRing.Foreground = new SolidColorBrush(Colors.White);
                                        txtTemperatureRing.Text = "°";
                                        txtTemperatureRing.TextAlignment = TextAlignment.Right;

                                            txtTemperature.FontFamily = new FontFamily("Segoe WP Light");
                                            txtTemperature.FontSize = 60;
                                            txtTemperature.Margin = new Thickness { Left = 0, Bottom = 0, Right = 0, Top = -75 };
                                            txtTemperature.Height = 80;
                                            txtTemperature.Width = 145;
                                            txtTemperatureRing.Margin = new Thickness { Left = 128, Bottom = 0, Right = 0, Top = -97 };
                                            txtTemperatureRing.Height = 50;
                                            txtTemperatureRing.Width = 39;

                                        sp.Children.Add(img3);
                                        sp.Children.Add(txtTemperature);
                                        sp.Children.Add(txtTemperatureRing);


                                        //call measure, arrange and updatelayout to prepare for rendering
                                        sp.Measure(new Size(173, 173));
                                        sp.Arrange(new Rect(0, 0, 173, 173));
                                        sp.UpdateLayout();
                                        grid.Children.Add(sp);


                                        WriteableBitmap wbmp = new WriteableBitmap(173, 173);
                                        wbmp.Render(grid, null);
                                        wbmp.Invalidate();


                                        //write image to isolated storage
                                        string sIsoStorePath = @"\Shared\ShellContent\tile.png";
                                        using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                                        {
                                            //ensure directory exists
                                            String sDirectory = System.IO.Path.GetDirectoryName(sIsoStorePath);
                                            if (!appStorage.DirectoryExists(sDirectory))
                                            {
                                                appStorage.CreateDirectory(sDirectory);
                                            }

                                            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(sIsoStorePath, System.IO.FileMode.Create, appStorage))
                                            {
                                                wbmp.SaveJpeg(stream, 173, 173, 0, 100);
                                            }
                                        }


                                        /// If application uses both PeriodicTask and ResourceIntensiveTask


                                            //ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileID=2"));
                                            ShellTile TileToFind = ShellTile.ActiveTiles.First();

                                            //test if Tile was created
                                            if (TileToFind != null)
                                            {
                                                StandardTileData NewTileData = new StandardTileData
                                                {
                                                    BackgroundImage = new Uri("isostore:Shared/ShellContent/tile.png", UriKind.Absolute),
                                                    Title = strTitle,
                                                    Count = null,
                                                    BackTitle = (string)settings["SelectedCityName"],
                                                    BackBackgroundImage = new Uri(strBackBackground, UriKind.Relative),
                                                    BackContent = strWind + Environment.NewLine + strPrecipitation
                                                };

                                                //ShellTile.Create(new Uri("/MainPage.xaml?TileID=2", UriKind.Relative), NewTileData);
                                                TileToFind.Update(NewTileData);

                                            }
                                        }



                                        if (runNotifyComplete == true)
                                        {
                                            runNotifyComplete = false;
                                            NotifyComplete();
                                        }
                                    }//If matches.count
                                }
                                catch
                                {
                                    if (runNotifyComplete == true)
                                    {
                                        runNotifyComplete = false;
                                        NotifyComplete();
                                    }
                                }
                                finally
                                {
                                    if (runNotifyComplete == true)
                                    {
                                        runNotifyComplete = false;
                                        NotifyComplete();
                                    }
                                }
                            }));
                        }



                        if (runNotifyComplete == true)
                        {
                            runNotifyComplete = false;
                            NotifyComplete();
                        }

                    }
                    catch
                    {


                        // error handling.
                        if (runNotifyComplete == true)
                        {

                            runNotifyComplete = false;
                            NotifyComplete();
                        }
                    }
                    finally
                    {
                    }
                },
                request);
        }
        catch
        {
            if (runNotifyComplete == true)
            {
                runNotifyComplete = false;
                NotifyComplete();
            }
        }
        finally
        {
        }

编辑1:这是初始化后台任务的代码 MessageBox.Show(MyResources.LiveTileToggleMsgBoxText, "活动磁贴", MessageBoxButton.OK);

              //start background agent 
            PeriodicTask periodicTask = new PeriodicTask("AppPeriodicAgent0440");

            periodicTask.Description = "Periodic task for APP that updates the LiveTile .";
            periodicTask.ExpirationTime = System.DateTime.Now.AddDays(14);

            // If the agent is already registered with the system,
            if (ScheduledActionService.Find(periodicTask.Name) != null)
            {
                ScheduledActionService.Remove("AppPeriodicAgent0440");
            }

            try
            {
                //only can be called when application is running in foreground
                ScheduledActionService.Add(periodicTask);
            }
            catch
            {
            }

编辑2: 每次退出应用程序时都会运行此代码,以保持后台任务处于活动状态。我将其放在 OnNavigateFrom 中以避免减慢应用程序的启动速度

//start background agent 
                        PeriodicTask periodicTask = new PeriodicTask("AppPeriodicAgent0440");

                        periodicTask.Description = "Periodic task for APP that updates the LiveTile.";
                        periodicTask.ExpirationTime = System.DateTime.Now.AddDays(14);

                        // If the agent is already registered with the system,
                        if (ScheduledActionService.Find(periodicTask.Name) != null)
                        {
                            ScheduledActionService.Remove("AppPeriodicAgent0440");
                        }

                        //only can be called when application is running in foreground
                        ScheduledActionService.Add(periodicTask);

I'm about to loose it soon... I have two apps with working background tasks that are updating the live tile. The data for the live tile is downloaded, parsed and then an image is created dynamically and used as the background for the live tile.

Everything is working just fine for a day or two, but then the updating starts behaving very strange. The first one-two days both live tiles for my apps are updating every 28 minutes like clockwork. But then they start skipping updates. Often app A then updates when app B doesn't update the live tile so that they are not updating at the same time and only once an hour. To put it simple they are way off schedule.

This is really frustrating since I need to be able to rely on the tiles beeing updated every 30 minutes (if I have enough battery, good reception and so on).

I would really appreciate if someone could help me out and maybe take a look at my code to see if there might be something messing up the update interval (like not calling NotifyComplete correctly). I have removed some code and and tried to simplify it. Please ask if you need anything else to understand this.

I have been trying to fix this for the last two months, trying different phones and going throughmy code very carefully.

Your help is more appreciated than you can ever know.
Thanks in advance.

My OnInvoke function:

        Timer t = null;

        ShellToast toast = new ShellToast();


        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(strUrlHBH));
            request.Accept = "*/*";
            request.AllowAutoRedirect = true;

            // disable caching.
            request.Headers["Cache-Control"] = "no-cache";
            request.Headers["Pragma"] = "no-cache";

            t = new Timer(
                state =>
                {
                    if (string.Compare(state.ToString(), id, StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        //logger.Write("Timeout reached for connection [{0}], aborting download.", id);
                        runNotifyComplete = false;
                        NotifyComplete();
                        request.Abort();
                        t.Dispose();
                    }

                },
                id,
                timeout,
                0);

            request.BeginGetResponse(
                r =>
                {
                    try
                    {
                        if (t != null)
                        {
                            t.Dispose();
                        }

                        var httpRequest = (HttpWebRequest)r.AsyncState;
                        var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);
                        using (var reader = new StreamReader(httpResponse.GetResponseStream()))
                        {

                            var response = reader.ReadToEnd();

                            Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                try
                                {

                                    //Parse the result

                                    if (boolResult) //If we have a result
                                    {


                                        Grid grid = new Grid();



                                        StackPanel sp = new StackPanel();
                                        sp.Height = 173;
                                        sp.Width = 173;



                                        //StreamResourceInfo info = Application.GetResourceStream(new Uri("Pin-to-start2.png", UriKind.Relative));


                                        if ((bool)settings["LiveTileMetro"] == true)
                                        {

                                            // create source bitmap for Image control (image is assumed to be alread 173x173)
                                            /*WriteableBitmap wbmp2 = new WriteableBitmap(1, 1);
                                            wbmp2.SetSource(info.Stream);
                                            Image img = new Image();
                                            img.Source = wbmp2;
                                            // add Image to Grid
                                            grid.Children.Add(img);
                                            strBackBackground = "Pin-to-start2.png";
                                        }
                                        else
                                        {*/
                                            sp.Background = (SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"];
                                            //sp.Background.Opacity = 0.0;
                                            strBackBackground = "";
                                        }

                                        StreamResourceInfo info;

                                        //GC.Collect();
                                        info = Application.GetResourceStream(new Uri("/MyApp;component/images/Icons/livetile/livetile.png", UriKind.Relative));


                                        WriteableBitmap wbmp3 = new WriteableBitmap(1, 1);
                                        try
                                        {
                                            wbmp3.SetSource(info.Stream);
                                        }
                                        catch
                                        {
                                        }
                                        Image img3 = new Image();
                                        img3.Source = wbmp3;
                                        // add Image to Grid
                                        img3.Width = 173;
                                        img3.Height = 173;
                                        img3.Margin = new Thickness { Left = 0, Bottom = 0, Right = 0, Top = 0 };


                                        TextBlock txtTemperature = new TextBlock();
                                        TextBlock txtTemperatureRing = new TextBlock();

                                        txtTemperature.Foreground = new SolidColorBrush(Colors.White);
                                        txtTemperature.Text = strTemp;
                                        txtTemperature.TextAlignment = TextAlignment.Right;
                                        txtTemperatureRing.Style = (Style)Application.Current.Resources["PhoneTextTitle3Style"];
                                        txtTemperatureRing.FontFamily = new FontFamily("Segoe WP Light");
                                        txtTemperatureRing.FontSize = 40;
                                        txtTemperatureRing.Foreground = new SolidColorBrush(Colors.White);
                                        txtTemperatureRing.Text = "°";
                                        txtTemperatureRing.TextAlignment = TextAlignment.Right;

                                            txtTemperature.FontFamily = new FontFamily("Segoe WP Light");
                                            txtTemperature.FontSize = 60;
                                            txtTemperature.Margin = new Thickness { Left = 0, Bottom = 0, Right = 0, Top = -75 };
                                            txtTemperature.Height = 80;
                                            txtTemperature.Width = 145;
                                            txtTemperatureRing.Margin = new Thickness { Left = 128, Bottom = 0, Right = 0, Top = -97 };
                                            txtTemperatureRing.Height = 50;
                                            txtTemperatureRing.Width = 39;

                                        sp.Children.Add(img3);
                                        sp.Children.Add(txtTemperature);
                                        sp.Children.Add(txtTemperatureRing);


                                        //call measure, arrange and updatelayout to prepare for rendering
                                        sp.Measure(new Size(173, 173));
                                        sp.Arrange(new Rect(0, 0, 173, 173));
                                        sp.UpdateLayout();
                                        grid.Children.Add(sp);


                                        WriteableBitmap wbmp = new WriteableBitmap(173, 173);
                                        wbmp.Render(grid, null);
                                        wbmp.Invalidate();


                                        //write image to isolated storage
                                        string sIsoStorePath = @"\Shared\ShellContent\tile.png";
                                        using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                                        {
                                            //ensure directory exists
                                            String sDirectory = System.IO.Path.GetDirectoryName(sIsoStorePath);
                                            if (!appStorage.DirectoryExists(sDirectory))
                                            {
                                                appStorage.CreateDirectory(sDirectory);
                                            }

                                            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(sIsoStorePath, System.IO.FileMode.Create, appStorage))
                                            {
                                                wbmp.SaveJpeg(stream, 173, 173, 0, 100);
                                            }
                                        }


                                        /// If application uses both PeriodicTask and ResourceIntensiveTask


                                            //ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileID=2"));
                                            ShellTile TileToFind = ShellTile.ActiveTiles.First();

                                            //test if Tile was created
                                            if (TileToFind != null)
                                            {
                                                StandardTileData NewTileData = new StandardTileData
                                                {
                                                    BackgroundImage = new Uri("isostore:Shared/ShellContent/tile.png", UriKind.Absolute),
                                                    Title = strTitle,
                                                    Count = null,
                                                    BackTitle = (string)settings["SelectedCityName"],
                                                    BackBackgroundImage = new Uri(strBackBackground, UriKind.Relative),
                                                    BackContent = strWind + Environment.NewLine + strPrecipitation
                                                };

                                                //ShellTile.Create(new Uri("/MainPage.xaml?TileID=2", UriKind.Relative), NewTileData);
                                                TileToFind.Update(NewTileData);

                                            }
                                        }



                                        if (runNotifyComplete == true)
                                        {
                                            runNotifyComplete = false;
                                            NotifyComplete();
                                        }
                                    }//If matches.count
                                }
                                catch
                                {
                                    if (runNotifyComplete == true)
                                    {
                                        runNotifyComplete = false;
                                        NotifyComplete();
                                    }
                                }
                                finally
                                {
                                    if (runNotifyComplete == true)
                                    {
                                        runNotifyComplete = false;
                                        NotifyComplete();
                                    }
                                }
                            }));
                        }



                        if (runNotifyComplete == true)
                        {
                            runNotifyComplete = false;
                            NotifyComplete();
                        }

                    }
                    catch
                    {


                        // error handling.
                        if (runNotifyComplete == true)
                        {

                            runNotifyComplete = false;
                            NotifyComplete();
                        }
                    }
                    finally
                    {
                    }
                },
                request);
        }
        catch
        {
            if (runNotifyComplete == true)
            {
                runNotifyComplete = false;
                NotifyComplete();
            }
        }
        finally
        {
        }

EDIT 1: Here is the code for initializing the background task
MessageBox.Show(MyResources.LiveTileToggleMsgBoxText, "Live tile", MessageBoxButton.OK);

              //start background agent 
            PeriodicTask periodicTask = new PeriodicTask("AppPeriodicAgent0440");

            periodicTask.Description = "Periodic task for APP that updates the LiveTile .";
            periodicTask.ExpirationTime = System.DateTime.Now.AddDays(14);

            // If the agent is already registered with the system,
            if (ScheduledActionService.Find(periodicTask.Name) != null)
            {
                ScheduledActionService.Remove("AppPeriodicAgent0440");
            }

            try
            {
                //only can be called when application is running in foreground
                ScheduledActionService.Add(periodicTask);
            }
            catch
            {
            }

EDIT 2:
This code is run everytime I exit the application in order to keep the background task alive. I put it in OnNavigatedFrom to avoid slowing down the start up of the app

//start background agent 
                        PeriodicTask periodicTask = new PeriodicTask("AppPeriodicAgent0440");

                        periodicTask.Description = "Periodic task for APP that updates the LiveTile.";
                        periodicTask.ExpirationTime = System.DateTime.Now.AddDays(14);

                        // If the agent is already registered with the system,
                        if (ScheduledActionService.Find(periodicTask.Name) != null)
                        {
                            ScheduledActionService.Remove("AppPeriodicAgent0440");
                        }

                        //only can be called when application is running in foreground
                        ScheduledActionService.Add(periodicTask);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傻比既视感 2024-12-28 17:08:43

如果您阅读了后台代理概述
http://msdn.microsoft.com/en-us/library/hh202942(v=vs.92).aspx 您将看到它详细说明了您的安排不会被遵循的几种情况。例如:

省电模式是用户可以在设备上启用的选项
表明应优先考虑电池寿命。如果这个模式是
启用后,即使间隔已过,定期代理也可能不会运行

If you read the Background Agents overview
http://msdn.microsoft.com/en-us/library/hh202942(v=vs.92).aspx you'll see that it details several scenarios where you schedule won't be followed. For example:

Battery Saver mode is an option that the user can enable on the device
to indicate that battery life should be prioritized. If this mode is
enabled, periodic agents may not run, even if the interval has elapsed

鱼窥荷 2024-12-28 17:08:43

无法保证计划任务将按预期计划运行。它甚至在执行时间表中有一个 +/- 10 分钟的子句。

从您的问题来看,没有关于您如何记录在您期望计划运行时设备上可能发生的其他事件/任务的信息。

由于您没有记录错误、超时或检查任务的 LastExitReason,因此您所看到的行为可能有各种原因。

如果我必须根据您提供的信息猜测问题出在哪里,我认为问题出在 Web 请求(网络或服务器)上,并且请求中的错误会导致 UI 无法更新。

无法保证磁贴将按可预测的时间表更新。如果您绝对必须根据您的情况/要求进行更新,那么该平台将无法提供该保证。

如果您需要多个图块保持同步,我会通过同一进程更新所有图块来实现此目的。
这样,即使从时间角度来看图块的更新存在不一致,它们也会彼此同步。

There is no guarantee that the scheduled task will run on the expected schedule. It even has a +/- 10 minute clause in the execution timeschedule.

From your question there is no information about how you're recording other events/tasks that may be happenening on the device at the time you're expecting a schedule to run.

In that you have no logging of errors, timeouts or checking of the LastExitReason of the task there could be all sorts of reasons for the behaviour you're seeing.

If I had to guess where the issue is, based on the information you have provided, I'd presume the problem is with the web request (either the network or the server) and an error in the request causes the UI to not be updated.

There is no way to guarantee that the tile will update on a predictable schedule. If you must absolutely have this updated for your circumstances/requirements then this platform isn't going to be able to provide that guarantee.

If you need multiple tiles to be kept in sync I'd approach this by having all the tiles updated by the same process.
This way, even if there is an inconsistency in the updating of the tiles from a time perspective they'll be in sync with each other.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文