C# WP8后台代理-代码在代理外部执行良好,在内部失败?

C# WP8后台代理-代码在代理外部执行良好,在内部失败?,c#,windows-phone-8,background-agents,C#,Windows Phone 8,Background Agents,我创建了一个后台代理来更新我的live互动程序。代理可以很好地调度和执行,但是代理执行的代码成了问题——它无法完全执行,并且没有提供任何错误。据我所知,我使用的API没有受到限制,除非Cimbalino工具包以某种方式提供了一个问题,即使我使用的是NuGet提供的特定于后台代理的版本 当RenderText()和RenderTextWide()无法运行时,代码似乎停止执行。没有提供任何错误。当在前台应用程序中运行时,同样的代码工作得非常好 using System; using System.W

我创建了一个后台代理来更新我的live互动程序。代理可以很好地调度和执行,但是代理执行的代码成了问题——它无法完全执行,并且没有提供任何错误。据我所知,我使用的API没有受到限制,除非Cimbalino工具包以某种方式提供了一个问题,即使我使用的是NuGet提供的特定于后台代理的版本

当RenderText()和RenderTextWide()无法运行时,代码似乎停止执行。没有提供任何错误。当在前台应用程序中运行时,同样的代码工作得非常好

using System;
using System.Windows;
using Microsoft.Phone.Scheduler;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Info;
using Cimbalino.Phone.Toolkit;
using System.Linq;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Controls;
using System.IO.IsolatedStorage;
using Cimbalino.Phone.Toolkit.Extensions;

namespace ScheduledTaskAgent1
{
    public class ScheduledAgent : ScheduledTaskAgent
    {
        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;
                });
            }
        }

        /// Code to execute on Unhandled Exceptions
        private void ScheduledAgent_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                System.Diagnostics.Debugger.Break();
            }
        }

        //Method to create normal tile image
        private static void RenderText(string currproperty)
        {
            WriteableBitmap b = new WriteableBitmap(336, 336);
            var canvas = new Grid();
            canvas.Width = b.PixelWidth;
            canvas.Height = b.PixelHeight;
            var background = new Canvas();
            background.Height = b.PixelHeight;
            background.Width = b.PixelWidth;

            SolidColorBrush backColor = new SolidColorBrush(Colors.Transparent);
            background.Background = backColor;

            TextBlock currtemp = new TextBlock();
            currtemp.FontSize = 100;
            currtemp.FontFamily = new FontFamily("Segoe UI Light");
            currtemp.FontWeight = FontWeights.Bold;
            currtemp.Foreground = new SolidColorBrush(Colors.White);
            currtemp.Text = currproperty;
            currtemp.Margin = new Thickness(20, 10, 0, 0);
            currtemp.Width = b.PixelWidth - currtemp.Margin.Left * 2;
            canvas.Children.Add(currtemp);

            b.Render(background, null);
            b.Render(canvas, null);
            b.Invalidate();
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream imageStream = new IsolatedStorageFileStream("/Shared/ShellContent/BackBackgroundImage2.png", System.IO.FileMode.Create, isf))
                {

                    b.SavePng(imageStream);
                }
            }
        }

        //Method to create wide tile image
        private static void RenderTextWide(string currproperty)
        {
            WriteableBitmap b = new WriteableBitmap(691, 336);
            var canvas = new Grid();
            canvas.Width = b.PixelWidth;
            canvas.Height = b.PixelHeight;
            var background = new Canvas();
            background.Height = b.PixelHeight;
            background.Width = b.PixelWidth;

            //Created background color as Accent color
            SolidColorBrush backColor = new SolidColorBrush(Colors.Transparent);
            background.Background = backColor;

            TextBlock currtemp = new TextBlock();
            currtemp.FontSize = 100;
            currtemp.FontFamily = new FontFamily("Segoe UI Light");
            currtemp.FontWeight = FontWeights.Bold;
            currtemp.Foreground = new SolidColorBrush(Colors.White);
            currtemp.Text = currproperty;
            currtemp.Margin = new Thickness(20, 10, 0, 0);
            currtemp.Width = b.PixelWidth - currtemp.Margin.Left * 2;
            canvas.Children.Add(currtemp);

            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream imageStream = new IsolatedStorageFileStream("/Shared/ShellContent/WideBackBackgroundImage2.png", System.IO.FileMode.Create, isf))
                {
                    b.SavePng(imageStream);
                }
            }
        }

        //When task invokes, run the tile update code.
        protected override void OnInvoke(ScheduledTask task)
        {
            ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault();
            if (tile != null)
            {
                FlipTileData flipTile = new FlipTileData();
                flipTile.Title = "";
                flipTile.BackTitle = "Atmosphere";
                RenderText("Test");
                RenderTextWide("Test");
                flipTile.BackBackgroundImage = new Uri("/Assets/NewUI/1.PNG", UriKind.Relative); //Default image for Background Image Medium Tile 336x336 px
                flipTile.BackgroundImage = new Uri(@"isostore:/Shared/ShellContent/BackBackgroundImage2.png", UriKind.Absolute); //Generated image for Back Background 336x336

                flipTile.WideBackBackgroundImage = new Uri("/Assets/NewUI/2.PNG", UriKind.Relative); ////Default image for Background Image Wide Tile 691x336 px
                flipTile.WideBackgroundImage = new Uri(@"isostore:/Shared/ShellContent/WideBackBackgroundImage2.png", UriKind.Absolute);
                tile.Update(flipTile);

                //Tile updated, tell agent operation complete
                NotifyComplete();
            }
        }      
    }
}

我刚刚运行了您在后台代理中共享的代码,并附加了调试器,问题很明显——它引发了一个异常!准确地说,无效的跨线程访问异常。所有与UI相关的工作都必须在UI线程中进行,实例化控件和可写位图就是这样的工作

解决方案

您需要使用
Deployment.Current.Dispatcher.BeginInvoke
在适当的线程中调用
RenderText
RenderTextWide
。您还可以在UI线程中调用
OnInvoke
中的所有内容

注意:
Deployment.Current.Dispatcher.BeginInvoke
异步调用给定的操作,因此如果没有在UI线程上运行所有操作,则可能需要执行一些操作来同步不同的线程

NotifyComplete

完成所有工作后,必须始终调用
NotifyComplete
。基本上,您需要做的是尝试catch(all),然后调用
NotifyComplete
。此外,为了以防万一,您可能需要将其放入
ScheduledAgent\u UnhandledException

NotifyComplete
不应该像在代码中那样出现在
if
中,尽管这种情况在Windows Phone中总是正确的
ShellTile.ActiveTiles
始终至少有一个互动程序-主互动程序-即使它没有固定

调试后台代理程序

是的,你能做到。如果代理不工作,查看问题所在的最佳方法是启动附加了调试器的应用程序,强制后台代理调用,并在要检查的代码中设置断点。用于比正常情况更快地启动后台代理

非主题/问题


我想问一下,您想用
私有静态易失性bool\u Classificationed
字段实现什么?为什么它是易变的呢?

在从WP8.0升级到WP8.1 Silverlight之后,我也看到了我的应用程序的这个问题。我的计划代理在我的代码中的任意点(生成活动分幅)完全无声地“崩溃”。崩溃或挂起经常发生,并且不会引发异常。我已经断断续续地做了一个多月了,但没有成功。我一直认为问题是我自己造成的。我昨晚确实找到了一份推荐信,这可能就是解决办法。我还没有在我的应用程序中完全测试它

在WP8.1 Silverlight API变更说明中,有一段非常隐晦的话:

使托管Windows Phone 8 ScheduledTaskAgent能够访问 Silverlight 8.1的特点是,它运行在现代执行堆栈上 与窗口聚合。这使用了不同的CPU配额机制 而不是WindowsPhone8。在某些情况下,Silverlight 8.1背景 代理可能会发现它获得的CPU时间比以前少。如果 在这种情况下,应用程序可能会选择调用RequestAccessAsync()。这 将增加分配给代理的CPU配额

我发现一些帖子指出,当在添加后台代理任务之前立即放置以下代码时,会修复一些问题:

await Windows.ApplicationModel.Background.BackgroundExecutionManager.RequestAccessAsync();
我很想知道其他人是否看到了这些类型的问题,以及这是否有助于他们。

解决了

我有同样的问题,我用以下代码解决了:

Deployment.Current.Dispatcher.BeginInvoke(委托(){RenderText(“Test”);}); Deployment.Current.Dispatcher.BeginInvoke(委托(){RenderTextWide(“Test”);})

文件ScheduledAgent.cs:

    protected override void OnInvoke(ScheduledTask task)
    {
        ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault();
        if (tile != null)
        {
            FlipTileData flipTile = new FlipTileData();
            flipTile.Title = "";
            flipTile.BackTitle = "Atmosphere";

            Deployment.Current.Dispatcher.BeginInvoke(delegate() { RenderText("Test"); });
            Deployment.Current.Dispatcher.BeginInvoke(delegate() { RenderTextWide("Test"); });

            flipTile.BackBackgroundImage = new Uri("/Assets/NewUI/1.PNG", UriKind.Relative); //Default image for Background Image Medium Tile 336x336 px
            flipTile.BackgroundImage = new Uri(@"isostore:/Shared/ShellContent/BackBackgroundImage2.png", UriKind.Absolute); //Generated image for Back Background 336x336

            flipTile.WideBackBackgroundImage = new Uri("/Assets/NewUI/2.PNG", UriKind.Relative); ////Default image for Background Image Wide Tile 691x336 px
            flipTile.WideBackgroundImage = new Uri(@"isostore:/Shared/ShellContent/WideBackBackgroundImage2.png", UriKind.Absolute);
            tile.Update(flipTile);

            //Tile updated, tell agent operation complete
            NotifyComplete();
        }
    }

当然,你已经访问过这里,我也访问过,除了内存上限之外,没有任何东西可以阻止它运行,我对此一无所知。我将研究日志记录方法是否也会更改为ResourcesIntensiveTask?@MikkoViitala您是否阅读了您给出的第一个链接的所有内容,尤其是关于ResourcesIntensiveTask的部分?它可能永远不会跑!它是完全不可靠的,不应该用于任何重要的事情!我非常怀疑这是凯文想要的…@Kevin你有没有试过安装调试程序的后台任务?我认为在这种情况下不会应用约束,因此您将看到在没有约束的情况下它是否有效。您可以使用强制启动后台任务。此外,您还可以获得任务使用的内存量。它对我有效。至少浪费了4天的时间。后台任务用于崩溃,无需尝试捕获即可修复。