我创建了一个后台代理来更新我的实时磁贴。代理程序调度并执行正常,但代理程序执行的代码已成为问题 - 它无法完全执行并且不会提供任何错误。据我所知,我没有使用受限制的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();
}
}
}
}
答案 0 :(得分:3)
我刚刚运行了你在附加调试器的后台代理中共享的代码,问题非常明显 - 它抛出异常!准确无效的跨线程访问异常。所有与UI相关的工作必须在UI线程中进行,并且实例化控件和WriteableBitmaps就是这样的工作。
<强>解决方案强>
您需要使用Deployment.Current.Dispatcher.BeginInvoke
在相应的主题中调用RenderText
和RenderTextWide
。您也可以在UI线程中调用OnInvoke
中的所有内容。
注意: Deployment.Current.Dispatcher.BeginInvoke
异步调用给定的操作,因此如果您不在UI线程上运行所有内容,则可能需要执行某些操作来同步不同的线程。
<强> NotifyComplete 强>
在完成所有工作后,您必须始终致电NotifyComplete
。基本上你需要做的是try-catch(全部),然后调用NotifyComplete
。此外,您可能希望将其放在ScheduledAgent_UnhandledException
以防万一。
NotifyComplete
不应与您的代码中的if
一样,尽管在Windows Phone中该条件始终为真。 ShellTile.ActiveTiles
始终至少有一个图块 - 主图块 - 即使它没有固定。
调试后台代理
是的,你可以这样做。如果代理无法正常工作,那么查看问题的最佳方法是在附加调试器的情况下启动应用程序,强制执行后台代理的调用并在要检查的代码中放置断点。使用ScheduledActionService.LaunchForTest
可以比平常更快地启动后台代理。
<强> Offtopic /问题强>
请问您在private static volatile bool _classInitialized
字段中想要实现的目标是什么?为什么它是volatile
?
答案 1 :(得分:2)
从WP8.0升级到WP8.1 Silverlight后,我的应用程序也遇到了这个问题。我的预定代理人在我的代码中的任意点绝对静默地“崩溃”(生成实时磁贴)。崩溃或挂起频繁发生,不会抛出任何异常。我已经在这个上下班了一个多月了但没有成功。我一直认为自己是以某种方式引起问题。昨晚我找到了一个可能是解决方案的参考。我还没有在我的应用程序中对它进行全面测试。
在WP8.1 Silverlight API更改说明中,有一段非常神秘的段落说:
使受管Windows Phone 8 ScheduledTaskAgent能够访问 Silverlight 8.1的功能,它运行在现代执行堆栈上 与Windows融合。这使用不同的CPU配额机制 比Windows Phone 8.在某些情况下,Silverlight 8.1背景 代理可能会发现它比以前更少的CPU时间。如果 发生这种情况时,应用程序可能会选择调用RequestAccessAsync()。这个 将增加给代理的CPU配额。
我发现了一些帖子elsewhere,表明以下代码修复了在添加后台代理任务之前立即放置的问题:
await Windows.ApplicationModel.Background.BackgroundExecutionManager.RequestAccessAsync();
我很想知道其他人是否看到了这些类型的问题,如果这有助于他们。
答案 2 :(得分:0)
解决!
我有同样的问题,我用以下代码解决了:
Deployment.Current.Dispatcher.BeginInvoke(delegate(){RenderText(“Test”);}); Deployment.Current.Dispatcher.BeginInvoke(delegate(){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();
}
}