• 【WP8.1开发】认识后台任务


    在手机上,使用后台,不像电脑上那么随意,准确地讲嘛,在移动平台上,后台任务都有严格的限制。至于说为什么会有这么多限制,我估计初衷很明显——保证系统的性能不受某个或某几个应用的负面影响;另外就是出于安全性考虑。

    毕竟手机设备不同于电脑,一旦后台程序泛滥成灾,是很难进行管理的,要防止这些不可预知的事件,只能从源头上杜绝。因此,当初在RT应用上就是:允许后台任务,但你得按规矩做人

    无规矩不成方圆,没有限制就会乱象横生,无法控制,现在某手机系统就深陷这一问题无法自拨,WP没有必要重蹈这一覆辙。

    好,前面废话了那么多,就是要告诉大家,在开发的时候一定要想清楚,到底该不该使用后台任务,使用后台任务的话,一定要自己亲测一下,是否会明显消耗电量,是否会产生庞大的网络流量。大家一定要养成一个好习惯——以做流氓程序为耻。说到这里,不得不鄙视一下国内的某些公司。

    既然后台任务是有限制的,那么,官方是通过什么方式来限制的呢?

    触发器:后台任务必须通过触发器来执行。这个触发器,可以理解为类似生物的条件反射。清单文件给出的触发类型有:后台音频、计时器、系统维护等。记得前面我写过博客,弄了一个在点亮屏幕时播放音乐,虽然这种做法不尽合理,但也作为一种参考吧。那个示例就是通过系统触发器中的UserPresent类型触发的,就是当用户把手机屏幕点亮这一行为发生后就会执行后台任务。

    比如,比较常用的还有计时器,这个应该会用得较多,比如每隔一段时间提取一批新闻列表等,如每30分钟就执行一次。当然这计时器是有限制的,常规要求是至少15分钟。不然的话,一些人品不端正的开发者弄个每分钟触发一次,那还得了,如果它是提取广告的话,那不断地弹广告就会把用户弹傻了。大家千万别干这种事,你要干这种事,我只能说你太没出息。

    凡是实现了IBackgroundTrigger接口的都是触发器,常以“Trigger”结尾,并不是所有触发器都能用,有些是需要申请的,比如ChatMessageNotificationTrigger,这也是防止恶意程序的做法。

    执行条件:这个主要由SystemCondition类表示。执行条件与触发器不同,触发器是表明在什么事实发生后执行后台任务,而执行条件是在什么情况下才能执行后台任务。你听起来好像意思接近,实际上是不同的。比如,如果你的后台任务需要从网络上获取数据,而且触发器为每25分钟一次的计时器,于是在注册后台任务时,你可以考虑增加一个执行条件:在有网络连接的前提下执行。虽然计时器的时间到了,但正好这个时候,由于用户的手机卡欠下4G流量费8622000元,被停机了,没法上网,那么系统检测到不存在有效的网络连接,就不执行后台任务了(可以考虑用WiFi)。

    如何使用后台任务

    前面扯了一堆臊话,主要是让朋友们对后台任务有个大致的了解,现在向大家介绍如何用后台。

    代表后台任务的代码通常应该写在一个独立的组件中,这样做也比较科学的,有些朋友在开发程序时,喜欢把所有功能都塞到一个主程序里,许多人在开发桌面程序时就喜欢这样,把所有功能都塞进一个exe中,连.dll都不舍得多用一个,我不喜欢这样做的,一般我是一个功能模板用一个独立的.dll,至于.exe用来放UI或者一些核心处理。

    因此,第一步是向解决方案中添加一个Windows运行时组件,看清楚,是运行时组件,最后会生成.wimd文件,如果是类库就会生成.dll文件。后台任务都应写在Windows运行时组件中。这个应该会了吧,就是在“解决方案资源管理器”中新建项目,然后选Windows运行时组件,输入项目名字就可以了,如果你不会这个,我只能告诉你:基础不扎实,举步艰难。

    然后在新建的运行时组件中定义一个类,一定要是public的,不要问我为什么(请复习程序集的可访问性),这个类要实现IBackgroundTask接口,表示它用于执行后台任务。

        public sealed class DemoTask : IBackgroundTask
        {
            public void Run ( IBackgroundTaskInstance taskInstance )
            {
                
            }
        }

    重点是实现Run方法,当后台任务执行时,就是调用这个方法的,你的后台任务要做什么就写在Run里面。
    注意到有个IBackgroundTaskInstance类型的参数,是个接口,我们不用管它哪个类实现,这个在系统调用时会自动赋值,只关心它有哪些成员即可。

    一定要明白GetDeferral方法的作用,它可以返回一个BackgroundTaskDeferral对象,这个对象的作用,说简单一点就是用来拖延时间的,就是拖延后台任务的时间,当你觉得后台任务已经完成了,就调用用BackgroundTaskDeferral的Complete方法,告诉系统:任务做完了,系统收到报告后,就可以清理该任务了。

    现在我们来实现一下这个任务。

            public void Run ( IBackgroundTaskInstance taskInstance )
            {
                var def = taskInstance.GetDeferral();
                // 获取XML模板
                XmlDocument docx = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
                // 修改XML
                var eles = docx.GetElementsByTagName("text");
                if (eles.Count < 2)
                {
                    def.Complete();
                    return;
                }
                XmlElement text01 = (XmlElement)eles[0];
                text01.AppendChild(docx.CreateTextNode("示例"));
                XmlElement text02 = (XmlElement)eles[1];
                text02.AppendChild(docx.CreateTextNode("后台任务执行了。"));
    
                // 产生Toast通知
                ToastNotification notification = new ToastNotification(docx);
                // 显示通知
                ToastNotificationManager.CreateToastNotifier().Show(notification);
    
                // 报告任务完成
                def.Complete();
            }


    这个任务,不复杂,就是向用户发一条Toast通知。

    好,后台任务已经写好了,现在要在主项目中对它进行引用,一定不要忘了,只有引用了上面写的Windows运行时组件才能访问它,这和以前.net项目一样。

    这个后台任务,我打算让它每40分钟执行一次,所以触发器应选用TimeTrigger。下面先简单设计一下UI。

        <StackPanel>
            <Button Content="注册后台任务" Click="开始注册"/>
            <Button Content="取消后台任务" Click="取消注册"/>
            <TextBlock x:Name="tb" FontSize="20" TextWrapping="Wrap"/>
        </StackPanel>

    界面简单,你看得懂的,其实事件处理的方法名是可以用中文的,在VS里面,类型名、命名空间名、成员名、参数名都可以用中文的,如果你不喜欢英文名字,可以用中文。

    通常,注册后台任务需要准备以下证件:

    1、个人身份证,即后台任务的名字,这个名字必须唯一,不能与现有的任务重复。

    2、户口本。即入口点,指的是我们前面在Windows运行时组件中定义的那个类的类名,就是那个实现IBackgroundTask接口以及Run方法的类。

    为了在输入代码时不容易输入,最好先将这些内容声明为常量。

            /// <summary>
            /// 任务的唯一名称
            /// </summary>
            const string TASK_NAME = "haha_task";
            /// <summary>
            /// 入口点
            /// </summary>
            const string ENTRY_POINT = "BackTest.DemoTask";

    注意,入口点的名字是要包含命名空间名字的。

    好,前期手续基本办完,现在可以正式注册了。下面代码分别用于注册和取消注册后台任务。

            private async void 开始注册 ( object sender, RoutedEventArgs e )
            {
                var res = await BackgroundExecutionManager.RequestAccessAsync();
                if (res != BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity)
                    return;
    
                // 注册
                BackgroundTaskBuilder bd = new BackgroundTaskBuilder();
                bd.Name = TASK_NAME; //任务名
                bd.TaskEntryPoint = ENTRY_POINT; //入口点
                // 设置触发器为计时器
                bd.SetTrigger(new TimeTrigger(40, false));
                try
                {
                    BackgroundTaskRegistration reg = bd.Register();
                    // 注册成功,显示结果
                    tb.Text = string.Format("任务名:{0}
    任务ID:{1}", reg.Name, reg.TaskId);
                }
                catch (Exception ex)
                {
                    tb.Text = ex.Message;
                }
            }
    
            private void 取消注册 ( object sender, RoutedEventArgs e )
            {
                // 先查找一下是否已经注册了任务
                var task = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(t => t.Name == TASK_NAME);
                if (task != null)
                {
                    // 取消
                    task.Unregister(true);
                }
            }


    1、在注册之前一定要调用BackgroundExecutionManager.RequestAccessAsync方法,是然不会弹出任何提示,但不要忘了,不调用是不能注册的。

    2、BackgroundTaskBuilder类,顾名思义,就是用来注册后台任务的。

    3、TimeTrigger触发器的构造函数的第二个参数如果为true,那后台任务只运行一次,这里我希望它每40分钟运行一次,所以为false。

    现在,离成果不远了,但是还有一步很关键,那就是配置清单文件。

    打开Package.appxmanifest文件,切换到“声明”选项页,在可用的声明列表中选“后台任务”,然后点击添加按钮。

    在右边的页面中,按实际情况勾选,我这个例子是计时的,所以选计时器,然后在下面再填写一下入口点,这个入口点和注册后台任务时用的入口点是一样的,可以直接从刚才的代码中复制过来。

    因为本例要用到Toast通知,所以要让应用支持Toast。切换到“应用程序”选项卡,在下面有关通知设置的地方,将支持Toast通知设置为“是”。

    最后,保存并关闭清单文件。

    如何调试后台任务

    像我这个例子,要等40分钟才执行的,难道我在干等不成? 非也,我们不用在那里苦等40分钟,VS会帮助我们进行调试的。

    首先,运行应用程序,然后点页面上的注册按钮,确保后台任务已经成功注册。

    然后回到VS,在“调试位置”工具上,点击“生命周期事件”按钮右边的下拉箭头,从下拉菜单中你会看到有后台任务的名字。如下图。

    如果看不到,你可以稍等一下,如果一直不出现,你可以重复上面的步骤。只要后台任务注册成功的,肯定会显示的(后台音频和推送通知除外)。

    所以,现在你调试后台任务就很方便,直从“调试位置”工具栏的下拉菜单中选中后台任务,后台任务就会执行了。

    OK,相信通过这篇破文,初学者能够初步认识后台任务。

    示例源码:http://files.cnblogs.com/tcjiaan/SampleAppBackTask.zip

  • 相关阅读:
    Report studio交叉表求指定维度和的问题
    Cognos清除本地高速缓存的利与弊
    学习技巧-如何在IBM官网寻找学习资料
    Cognos利用DMR与文本对象设计中国式报表
    Cognos Report Studio 链接查询需要注意的地方2
    linux下自己下载的程序装哪?
    maven编译war包,pom中必须有的几个dependency
    跨站请求伪造解决办法之——过滤referer
    tomcat禁用webdav
    Tomcat配置https
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/4168910.html
Copyright © 2020-2023  润新知