我正在开发一个Windows Phone 8.1应用程序,该应用程序为每小时操作注册一个后台任务计时器触发器。基本上,后台任务每60分钟唤醒并执行一些操作。
我的问题是,当后台任务正在进行时,如果用户唤醒了应用程序,是否有办法向用户显示后台任务流程中发生了什么?
我知道它们是两个不同的过程。我正在为前台应用程序使用Silverlight 8.1项目,为后台任务使用托管的Windows运行时项目。我正在使用silverlight应用程序注册后台任务,但我现在正在考虑如何在这两个进程之间建立通信桥梁。
任何线索?这甚至可能吗?
答案 0 :(得分:5)
以下是有关应用与其后台任务之间通信的一些想法(或信息)。
您可以使用IBackgroundTaskRegistration对象的“进度”和“已完成”事件。您可以使用BackgroundTaskRegistration.AllTasks获取该对象 - 此属性返回应用程序注册的后台任务列表。每次应用程序运行时,您都必须订阅这些事件。
从后台任务中,您可以将IBackgroundTaskInstance对象的Progress属性设置为某个UInt32值,应用程序将接收该事件。也许你可以用这个数字编码你需要的东西。例如:1表示任务正在初始化,2 - 任务正在进行WorkA,依此类推......
这两个进程都可以访问相同的文件,所以也许你可以将它用于某些东西。
使用Mutex同步两个进程之间的代码执行。
这就是我现在所能想到的。我希望它有所帮助。
P.S。我没有真正尝试过那些事件,但看起来它们似乎很有用。
答案 1 :(得分:1)
我已经在通信b / w后台任务和自己的应用程序上做了一些POC。我正在使用Windows通用应用程序,但它也适用于silverlight手机应用程序。
private IBackgroundTaskRegistration timeZoonChangeTask;
public MainPage()
{
this.InitializeComponent();
NavigationHelper nvHelper = new NavigationHelper(this);
IReadOnlyDictionary<Guid, IBackgroundTaskRegistration> allTasks = BackgroundTaskRegistration.AllTasks;
if (allTasks.Count() == 0)
{
lblMessage.Text = "No Task is registered at the moment";
}
else//Task already registered
{
lblMessage.Text = "Timezoon Task is registered";
this.GetTask();
}
}
/// <summary>
/// Time zoon task registration.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void Button_Click(object sender, RoutedEventArgs e)
{
await BackgroundExecutionManager.RequestAccessAsync();
BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder();
taskBuilder.Name = "MyBackgroundTask";
SystemTrigger systemTrigger = new SystemTrigger(SystemTriggerType.TimeZoneChange, false);
taskBuilder.SetTrigger(systemTrigger);
taskBuilder.TaskEntryPoint = typeof(MyBackgroundTask.TheTask).FullName;
taskBuilder.Register();
lblMessage.Text = "Timezoon Task is registered";
this.GetTask();
}
/// Get registered task and handel completed and progress changed events.
/// </summary>
private void GetTask()
{
var timeZoonChangeTask = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault();
timeZoonChangeTask.Completed += timeZoonChangeTask_Completed;
timeZoonChangeTask.Progress += timeZoonChangeTask_Progress;
}
/// <summary>
/// raised when task progress is changed app is active
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
void timeZoonChangeTask_Progress(BackgroundTaskRegistration sender, BackgroundTaskProgressEventArgs args)
{
this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
lblTaskProgress.Text = args.Progress.ToString() + "%";
recProgress.Width = 400 * (double.Parse(args.Progress.ToString()) / 100);
});
//this.Dispatcher.BeginInvoke(() =>
// {
// });
}
/// <summary>
/// Raised when task is completed and app is forground
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
void timeZoonChangeTask_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
{
this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
lblMessage.Text = "Task Excecution is completed";
});
}
以下是任务类
public sealed class TheTask:IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
///Get Deferral if we are doing aysnc work. otherwise it will not work.
//Always get deferral it will not harm.
var deferral = taskInstance.GetDeferral();
taskInstance.Canceled += taskInstance_Canceled;
for (uint i = 0; i < 10; i++)
{
taskInstance.Progress = i + 10;
await Task.Delay(2000);
}
//Write last run time somewhere so the gorground app know that at when last time this backgournd app ran.
///Set this progress to show the progesss on the forground app if it is running and you want to show it.
taskInstance.Progress = 0;
deferral.Complete();
}
void taskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
}
}