• 【Win10 应用开发】从前台应用触发后台任务


    有关后台任务的使用,估计大伙伴们不会陌生,而且老周曾经在某文中也简单讲述过。说到后台任务,老周想到了一个问题:有人问,后台任务一定要独立写到一个Runtime组件中吗,能不能写到主项目的代码中?

    老周严重地回答你:是可以的,在配置清单文件中,你只需要在Extension元素中指定Executable为主项目的.exe文件即可。

            <Extension Category="windows.backgroundTasks" EntryPoint="……" Executable="xxxx.exe">
              <BackgroundTasks>
                ……
              </BackgroundTasks>
            </Extension>

    其实,Executable可以设置为$targetnametoken$.exe,这样在生成应用时,会自动用.exe文件的实际名称替换$targetnametoken$标签。

    可是,老周非常严重地不推荐把后台任务写到主项目中,一则这不符合官方文档的常规性要求,不便于代码分类管理;二则,这种做法会带来严重的负面效果,如果后台任务激活时,前台应用没有运行倒无所谓,要是后台任务执行时前台应用正在运行,很可能会造成前台应用进程重启,给用户的感觉就是闪退。

    好,上面只是给大家普及一下常识,建议大家在干活时最好按规矩办事,别老喜欢搞那些另类行为,另类不代表创新,只不过是幼稚罢了。

    今天的主题是:我能不能在前台应用中,通过代码有目的地触发后任务呢?我们知道,常见的后台任务有后台音频、定时器、系统事件、网络传输控制等触发器,那有没有可以让我们手动去触发后台任务的触发器呢?

    有,它的名字叫ApplicationTrigger,使用它,你在前台代码中就可以随时激活后台任务,而且还可以向后台任务传递参数。当需要执行后台任务时,直接调用ApplicationTrigger实例的RequestAsync方法即可,如果没有意外(比如泥石流、山体滑坡、地震等),那么后台任务就会执行。

    原理已经跟大家交代了,下面还是用实例说话吧。

    首先我定义了这么个后台任务,你猜猜它是干吗用的。

        public sealed class BgTask : IBackgroundTask
        {
            public async void Run(IBackgroundTaskInstance taskInstance)
            {
                var d = taskInstance.GetDeferral();
                // 取出与触发器相关的数据
                ApplicationTriggerDetails details = taskInstance.TriggerDetails as ApplicationTriggerDetails;
    
                if (details != null)
                {
                    // 取出传递过来的参数
                    ValueSet ps = details.Arguments;
                    int na = Convert.ToInt32(ps["a"]);
                    int nb = Convert.ToInt32(ps["b"]);
    
                    // 开始进行运算
                    int x = na;
                    int res = 0;
                    while (x <= nb)
                    {
                        res += x;
                        x++;
                        await Task.Delay(30); //延时
                        // 报告进度
                        ReportProgress(taskInstance, (uint)x, (uint)nb);
                    }
    
                    // 保存计算结果
                    ApplicationData.Current.LocalSettings.Values["result"] = res;
                }
                d.Complete();
            }
    
            private void ReportProgress(IBackgroundTaskInstance instance, uint c, uint t)
            {
                ……
            }
        }


    人品高尚的你一定看出来了,这个任务主要是做加法运算的,指定一个起始值和一个最终值,从起始值开始相加,一直加到最终值,每加一次就把操作数+1。其中,每一轮运算后会拖延30毫秒,目的是方便看进度。本任务不太严谨,比如它没有检测如果终值小于始值时怎么处理,大家知道就行了,老周不想把代码搞复杂,仅供演示。

    然后你必须记得在主项目中引用写有后台任务类的Rutime组件项目。

    接下来,配置一下清单文件,打开Package.appxmanifest文件,找到Application节点,注意不是Applications节点,没有s的,随后加入扩展点。

        <Application Id="App" …… >
          ……
          <Extensions>
            <Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTasks.BgTask" >
              <BackgroundTasks>
                <Task Type="general"/>
              </BackgroundTasks>
            </Extension>
          </Extensions>
        </Application>

    <Task Type="general"/>表示该后任务是常规型,通用型,即大众化的后台任务,而不是精英级后台。

    清单文件只是作声明,后台任务不会自动注册,需要用代码来完成注册。

            const string TASK_NAME = "comptask";
            private BackgroundTaskRegistration taskReg = null;
            protected override async void OnNavigatedTo(NavigationEventArgs e)
            {
                var res = await BackgroundExecutionManager.RequestAccessAsync();
                if (res == BackgroundAccessStatus.Unspecified || res == BackgroundAccessStatus.Unspecified)
                {
                    ShowMessage("后台任务被禁用。"); return;
                }
    
                taskReg = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(t => t.Name == TASK_NAME) as BackgroundTaskRegistration;
                // 注册后台任务
                if (taskReg == null)
                {
                    BackgroundTaskBuilder bd = new BackgroundTaskBuilder();
                    // 入口点
                    bd.TaskEntryPoint = typeof(BackgroundTasks.BgTask).FullName;
                    // 任务名称
                    bd.Name = TASK_NAME;
                    // 设置触发器
                    ApplicationTrigger trigger = new ApplicationTrigger();
                    bd.SetTrigger(trigger);
                    taskReg = bd.Register();
                    ShowMessage("后台任务注册成功。");
                }
                // 添加事件处理
                taskReg.Progress += TaskReg_Progress;
                taskReg.Completed += TaskReg_Completed;
            }

    注册前应该访问BackgroundTaskRegistration.AllTasks看看你需要的后台任务是不是已经注册了,重复注册没有意义。

    下面代码通过ApplicationTrigger来触发后台任务。

                // 从注册的任务中取出触发器
                ApplicationTrigger trigger = taskReg.Trigger as ApplicationTrigger;
    
                // 准备参数
                ValueSet p = new ValueSet();
                p["a"] = n1;
                p["b"] = n2;
                // 触发后台任务
                var res = await trigger.RequestAsync(p);
                switch (res)
                {
                    case ApplicationTriggerResult.Allowed:
                        ShowMessage("后台任务已启动。");
                        break;
                    case ApplicationTriggerResult.CurrentlyRunning:
                        ShowMessage("后台任务已经在运行了。");
                        break;
                    case ApplicationTriggerResult.DisabledByPolicy:
                        ShowMessage("管理员不允许执行后台任务。");
                        break;
                    case ApplicationTriggerResult.UnknownError:
                        ShowMessage("发生错误。");
                        break;
       
    }

     在调用RequestAsync方法时,可以向后台任务传递数据,数据用ValueSet类封装,其实就是个字典模型,key为字符串。

    方法调用后,会返回ApplicationTriggerResult枚举的值。如果值为Allowed表明后台任务已成功触发;如果为CurrentlyRunning表明后台任务还在运行中,“你所拨打的号码正在通话中,请稍后再试”;如果值为DisabledByPolicy表示后台任务被禁止了。

    一切就绪,看看运行结果:

    呈现计算结果。

    本示例下载地址:http://files.cnblogs.com/files/tcjiaan/triggerbgtfromapp.zip

    好了,肚子饿了,要开饭,今天的白菜猪肉汤比较nice。有网友提出,老周能不能写一写Win10中Toast通知和操作中心的一些新知识点。没问题的,下一篇烂文开始,老周就和大伙伴们一起研究一下Adaptive Generic Toast吧。

  • 相关阅读:
    Tye exception
    DataSeeder
    angular
    认证Authentication
    MVC
    Ef Core
    工作单元
    VirtualFileSystem
    中间件
    日志
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/4658416.html
Copyright © 2020-2023  润新知