-
如何在服务停止后关闭Spring task executor/scheduler
2020-09-03 19:41:15转载自: How can I shutdown Spring task executor/scheduler pools before all other beans in the web app are destroyed?展开全文 -
Task Scheduler 2.0的相关操作
2017-02-26 23:05:53理解ITaskService对象此对象需要依赖TaskshdWindows服务,如果此服务被关闭,那么此COM对象也将会失效。了解ITaskService对象
此对象需要依赖TaskshdWindows服务,如果此服务被关闭,那么此COM对象也将会失效。有关这个COM对象在MSDN里也多有提及,想看官方的在线连接,[点我吧]
注意,Task Scheduler 2.0仅仅可以在Xp以上的Windows系统内可以正常使用哦。
操作Task Scheduler 2.0的常见套路
对于TaskScheduler 2.0而言,开发包括了以下常见步骤,如下所示:
- 1.调用
CoInitialize()
来初始化COM,代码片段如下所示:
CoInitialize(NULL);
- 2.调用
CoInitializeSecurity()
来设置进程安全,避免被杀毒软件报毒
代码如下所示:
CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL );
- 3.使用
CoCreateInstance()
函数来初始化一个ITaskService
对象。代码片段如下所示:
ITaskService *m_pService=NULL; CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (void ** )&m_pService);
- 4.在
Task Scheduler 2.0
之中,与1.0的不同之处就是需要通过ITaskService
对象里面的Connect()
来连接上对应的Windows服务程序。代码片段如下所示:
m_pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
5.调用
ITaskService
对象里面提供的各种操作方法,来执行相应的操作。如下图所示:6.操作完成之后,调用
CoUninitialize()
来释放COM。当然在此之前,需要对各个COM对象,比如ITaskService等COM对象执行
Release()`函数进行内存释放,如果使用了智能指针来管理了此对象,那自然就可以偷懒了(^__^)
- 1.调用
-
求助,win10系统task scheduler导致CPU占用100%
2017-03-14 02:37:28周一开机后task scheduler就开始运行,占用CPU70多,CPU总占用100,风扇一直响.(以前这个服务也运行过)。通过任务管理器,得手动关闭3次,才能把服务关掉,风扇不再响,但是过了一会,它又自己启动了。然后我就想... -
freertos之scheduler浅析
2018-12-29 12:47:40调度器开启、关闭 一般在调度器没有开启之前需要创建一个start_task来创建一系列任务task,然后就是调用vTaskStartScheduler来启动调度器。下面分析具体代码 void vTaskStartScheduler( void ) { BaseType_t xReturn...前言
其实是接上一篇task这篇文章的,上一篇写的有点多。
代码分析
调度器开启、关闭
一般在调度器没有开启之前需要创建一个start_task来创建一系列任务task,然后就是调用
vTaskStartScheduler
来启动调度器。下面分析具体代码void vTaskStartScheduler( void ) { BaseType_t xReturn; /* 创建idle task,使其运行在最低优先级 */ xReturn = xTaskCreate( prvIdleTask, "IDLE", configMINIMAL_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*如果使能了定时器功能,那么不论你之后会使用定时器功能, 都会先创建一个定时器函数*/ #if ( configUSE_TIMERS == 1 ) { if( xReturn == pdPASS ) { xReturn = xTimerCreateTimerTask(); } } if( xReturn == pdPASS ) {/*只有上两步操作都ok的情况下,才能继续执行*/ /*中断在这里被关闭,以确保在调用xPortStartScheduler()之前或期间不会发生tick。 已经创建的任务的栈中包含了开启中断的状态字,当第一个任务执行时, 中断将自动重新启用开始运行。*/ portDISABLE_INTERRUPTS(); xNextTaskUnblockTime = portMAX_DELAY; xSchedulerRunning = pdTRUE; xTickCount = ( TickType_t ) 0U; /* 计时器刻度的设置是决定于硬件的,因此在移植的接口设置。*/ if( xPortStartScheduler() != pdFALSE ){对于cm3平台来说就是systick定时器 } } } void vTaskEndScheduler( void ) { /* 停止中断,并调用可移植调度器停止函数,以便在必要时恢复原始ISRs。 可移植层必须确保中断启用位保持在正确的状态。*/ portDISABLE_INTERRUPTS(); xSchedulerRunning = pdFALSE; vPortEndScheduler(); }
阻塞调度器
在系统运行的时候如果不想让系统继续调度task运行,可以直接阻塞调度器,这样本来的任务就可以独占cpu了,不会被抢占打断。在做完工作之后在解挂就ok了
void vTaskSuspendAll( void ) { /* 由于该变量是BaseType_t类型的,所以不需要临界区*/ ++uxSchedulerSuspended; } BaseType_t xTaskResumeAll( void ) { TCB_t *pxTCB = NULL; BaseType_t xAlreadyYielded = pdFALSE; /*ISR可能导致从事件中删除任务在调度程序暂停时列出。 如果是这样,那么删除的任务将被添加到xPendingReadyList。 一旦已恢复调度程序,它是安全的移动所有挂起准备任务从这个列表进入相应的就绪列表。*/ taskENTER_CRITICAL();{ --uxSchedulerSuspended; if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ){ if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ){ /* 将 xPendingReadyList 中所有的的task移入 ReadyTasksLists中,所以用了个循环*/ while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ){ pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); /* If the moved task has a priority higher than the current task then a yield must be performed. */ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ){ xYieldPending = pdTRUE; } } if( pxTCB != NULL ){ /*当调度器被挂起的时候,可能导致了一个任务被阻塞了,而如果这个 任务恰好使得 xNextTaskUnblockTime 没有被重新计算, 那就在此重新计算。主要是对于低功耗无tickless实现 非常重要,这可以防止不必要的低功耗出口状态。*/ prvResetNextTaskUnblockTime(); } /*如果在调度器暂停时发生了tick,那么现在应该进行处理了。 这确保了tick计数不错乱,任何延迟的任务都在正确的时间恢复。*/ { UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */ if( uxPendedCounts > ( UBaseType_t ) 0U ){ do{ if( xTaskIncrementTick() != pdFALSE ){ xYieldPending = pdTRUE; } --uxPendedCounts; } while( uxPendedCounts > ( UBaseType_t ) 0U ); uxPendedTicks = 0; } } if( xYieldPending != pdFALSE ){ #if( configUSE_PREEMPTION != 0 ) {//这个返回值会导致内核抢占调度发生 xAlreadyYielded = pdTRUE; } #endif taskYIELD_IF_USING_PREEMPTION(); } } } } taskEXIT_CRITICAL(); return xAlreadyYielded; }
-
[BUG] 定时任务开启singleton后,TASK运行期间程序关闭后再打开互斥锁没有正常释放导致不运行
2021-01-08 20:59:44swoole.enable_preemptive_scheduler => Off => Off swoole.display_errors => On => On swoole.use_shortname => Off => Off swoole.unixsock_buffer_size => ... -
耗电优化(三):JobScheduler,WorkManager
2021-02-07 16:43:02(文章分成JobScheduler和WorkManager两个大部分,互不影响,可以自行查阅) 问题描述 在Android8.0以后的安卓手机上,为了实现App在后台的时候也能接收到服务器端的实时消息,使用了Service,然而在关闭App或进入...// 在android8.0以后的电量提醒问题。(文章分成JobScheduler和WorkManager两个大部分,互不影响,可以自行查阅)
问题描述
在Android8.0以后的安卓手机上,为了实现App在后台的时候也能接收到服务器端的实时消息,使用了Service,然而在关闭App或进入后台时,系统则会经常弹出一个无法清除掉的消息:“有耗电高的应用在后台”。
为了解决这个问题,我们查阅了Android开发者的官方文档,有关后台任务(Background Task)的部分。由于这部分文档只有英文的版本,所以简单说明一下:
它首先解释了不同的情况要如何选择最合适的解决方案。下面有一个表格简单说明了这个问题:
策略的选择
不知道上面这个表格看完,你有没有完全理解呢?
因为这篇文档中很多晦涩的专业英语,所以我在理解上也有很多的不解。总体来说它介绍了几种解决方案。其中似乎比较新的WorkManager还在测试阶段,所以我打算后面再去尝试,这里首先试试JobScheduler。在使用JobSchdeuler进行尝试的时候我首先找到了一个博客作为参考——JobScheduler API的使用详细:
首先我先创建了一个MyJobService类,执行的工作内容是向文件写入内容。
(在JobService中我还创建了一个AsyncTask用来异步写入文件)/** * 编译环境: Android Studio 3.1.4 Build #AI-173.4907809, built on July 24, 2018 JRE: 1.8.0_152-release-1024-b02 amd64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o Windows 10 10.0 */ package com.hongfei.intsig.backgrounddemo; import android.annotation.SuppressLint; import android.app.job.JobParameters; import android.app.job.JobService; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.AsyncTask; import android.util.Log; import java.io.File; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; @SuppressLint("NewApi") public class MyJobService extends JobService { private static final String TAG = "MyJobService"; @Override public boolean onStartJob(JobParameters jobParameters) { if (isNetworkConnected()) { new SimpleDownloadTask().execute(jobParameters); return true; } else { } return false; } @Override public boolean onStopJob(JobParameters jobParameters) { // Log.i(TAG, "stop job,名字是: " + jobParameters.getJobId()); return true; } private boolean isNetworkConnected() { ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = manager.getActiveNetworkInfo(); return (info != null && info.isConnected()); } private class SimpleDownloadTask extends AsyncTask<JobParameters, Void, String> { private JobParameters mJobParam; @Override protected String doInBackground(JobParameters... params) { mJobParam = params[0]; // 具体的后台操作 try{ File file = new File("/storage/emulated/0/1/testBackground.txt"); FileOutputStream fos = new FileOutputStream(file, true); SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd--HH时mm分ss秒SSS"); String content = "测试内容,JobID为:" + mJobParam.getJobId() + "。在时间:" + formatter.format(new Date()) + "打印完成\n"; byte [] bytes = content.getBytes(); fos.write(bytes); fos.close(); return "成功写入"; } catch(Exception e){ e.printStackTrace(); return "未成功! " + e.getMessage(); } } @Override protected void onPostExecute(String result) { jobFinished(mJobParam, true); super.onPostExecute(result); } } }
有了这个JobService之后,在MainActivity中,创建一个按钮,执行以下函数(创建一个Scheduler)
/** * 按钮的回调函数 */ @SuppressLint("NewApi") private void doBackgroundJob() { int jobId; // 创建三个id递增的job Service for (int i = 0; i < 3; i++) { jobId = 0; JobInfo jobInfo = new JobInfo.Builder(jobId, mJobService) .setMinimumLatency(10000)// 设置任务运行最少延迟时间 .setOverrideDeadline(60000)// 设置deadline,若到期还没有达到规定的条件则会开始执行 .setRequiresCharging(false)// 设置是否充电的条件 .setRequiresDeviceIdle(false)// 设置手机是否空闲的条件 .build(); mTvResult.append("scheduling job " + i + "。在时间:" + new Date().toString() + "!\n"); mJobScheduler.schedule(jobInfo); } }
点击按钮后,就会发现过了一段时间之后会打印出一段文字。
这里为了能够更好地理解,我们将按钮的回调函数改为下面的函数:/** * 按钮的回调函数修改 */ @SuppressLint("NewApi") private void doBackgroundJob() { int jobId = 201; for (int i = 0; i < 3; i++) { jobId = jobId + i; JobInfo jobInfo = new JobInfo.Builder(jobId, mJobService) .setPeriodic(MIN_PERIOD_MILLIS, MIN_FLEX_MILLIS) .build(); mJobScheduler.schedule(jobInfo); SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd--HH时mm分ss秒SSS"); try { File file = new File("/storage/emulated/0/1/testBackground.txt"); FileOutputStream fos = new FileOutputStream(file, true); String content = "开始计划任务,JobID为:" + jobId+ "。在时间:" + formatter.format(new Date()) + "打印完成\n"; byte [] bytes = content.getBytes(); fos.write(bytes); fos.close(); } catch (IOException e) { e.printStackTrace(); } mTvResult.append(formatter.format(new Date())+ "\n"); } }
这样就可以把大部分需要检查的内容都打印到日志文件中了。点击按钮之后,就把手机放在一边,任凭他关闭屏幕,就算把APP关闭到后台也无影响(但是不能强行清除后台。)
好了,这个调研就先到这里,让手机跑一会儿之后我把日志文件贴上来~现在我们转为去研究一下有关WorkManager的内容吧。1天后:我又翻开了测试机的测试文件,没想到昨天上午开始的Job,后来一直没怎么使用,Job的内容就这么奇怪,具体日志文件如下:
开始计划任务,JobID为:201。在时间:2018/10/11--11时07分07秒823打印完成 开始计划任务,JobID为:202。在时间:2018/10/11--11时07分07秒834打印完成 开始计划任务,JobID为:204。在时间:2018/10/11--11时07分07秒846打印完成 测试内容,JobID为:202。在时间:2018/10/11--11时17分22秒437打印完成 测试内容,JobID为:201。在时间:2018/10/11--11时17分22秒445打印完成 测试内容,JobID为:204。在时间:2018/10/11--11时17分22秒453打印完成 测试内容,JobID为:202。在时间:2018/10/11--11时17分52秒493打印完成 测试内容,JobID为:204。在时间:2018/10/11--11时17分57秒505打印完成 测试内容,JobID为:201。在时间:2018/10/11--11时17分57秒513打印完成 测试内容,JobID为:202。在时间:2018/10/11--11时18分52秒832打印完成 测试内容,JobID为:204。在时间:2018/10/11--11时18分57秒566打印完成 测试内容,JobID为:201。在时间:2018/10/11--11时19分02秒574打印完成 测试内容,JobID为:202。在时间:2018/10/11--11时21分52秒477打印完成 测试内容,JobID为:201。在时间:2018/10/11--11时21分52秒485打印完成 测试内容,JobID为:204。在时间:2018/10/11--11时21分52秒490打印完成 测试内容,JobID为:202。在时间:2018/10/11--11时25分52秒567打印完成 测试内容,JobID为:201。在时间:2018/10/11--11时25分57秒573打印完成 测试内容,JobID为:204。在时间:2018/10/11--11时25分57秒582打印完成 测试内容,JobID为:202。在时间:2018/10/11--11时33分52秒631打印完成 测试内容,JobID为:201。在时间:2018/10/11--11时33分57秒632打印完成 测试内容,JobID为:204。在时间:2018/10/11--11时34分02秒725打印完成 测试内容,JobID为:202。在时间:2018/10/11--11时50分14秒637打印完成 测试内容,JobID为:201。在时间:2018/10/11--11时50分14秒645打印完成 测试内容,JobID为:204。在时间:2018/10/11--11时50分14秒654打印完成 测试内容,JobID为:204。在时间:2018/10/11--12时22分32秒740打印完成 测试内容,JobID为:201。在时间:2018/10/11--12时22分32秒752打印完成 测试内容,JobID为:202。在时间:2018/10/11--12时22分32秒778打印完成 测试内容,JobID为:202。在时间:2018/10/11--18时01分27秒071打印完成 测试内容,JobID为:204。在时间:2018/10/11--18时01分27秒095打印完成 测试内容,JobID为:201。在时间:2018/10/11--18时01分27秒109打印完成 测试内容,JobID为:202。在时间:2018/10/11--22时48分53秒938打印完成 测试内容,JobID为:204。在时间:2018/10/11--22时48分53秒979打印完成 测试内容,JobID为:201。在时间:2018/10/11--22时48分53秒985打印完成
这时候使用命令行
adb shell'dumpsys jobscheduler | grep 包名'
的指令也终于发现没有后台Service了。
唯一能够确定的是使用JobScheduler的话,只要把APP清除了,就一定会停止任务。
WorkManager
从WorkManager的官方文档入手。
这一页大概只是说了:WorkMangaer是一个完全智能的任务分配器。你可以完全把要执行的任务丢给他,他就会帮你选择最优的办法(但是要是那种关闭程序就可以结束的任务就别扔给他啦,可以扔给线程池[ThreadPool])。
这后面有关WorkManager的部分还有两页,一页基础功能,一页进阶功能。
考虑到我们要实现的只是循环工作,我猜第一页-WorkManager basics的最后一部分-RecurringTasks就可以实现。总之我们先继续往下看吧~文章第一段就告诉我们,如果想要把WorkManager库导入你的项目,需要参考另外一篇文章-Adding Components to your Project.。
为了一会我们的项目能够正常使用WorkManager,这里我们就花些时间先把导入工作做好:
- 首先确保我们项目的compileSdk在28或以上(打开app级别的build.gradle文件)。
- 确保compileSdk在28以上之后,就可以在dependencies内添加下面两行语句
dependencies{ ... // 添加下面两行代码 def work_version = "1.0.0-alpha10" implementation "android.arch.work:work-runtime:$work_version" // use -ktx for Kotlin ... }
类和概念
简单介绍了几个WorkManager的重要类:
类名 说明 是否是抽象类 Worker 表明了要执行的任务。 √ WorkRequest 指明需要哪一个Worker去执行task 有两个子类OneTimeWrokRequest和PeriodicWorkRequest,顾名思义。而且都有各自的Build()方法 √ WorkManager 为你的WorkRequest们排序,管理 – WorkStatus 观测的状态 – 典型的工作流程
这种流程官网举了一个例子,类似于照片APP要不断的压缩处理存储的图片,这就是一个典型流程。重点是——你分配了这个任务以后就可以忘了它了,不需要关心什么时间真正的执行。
// todo:这里是单次执行的任务,和我们的需求不符合,之后再看。
任务限定条件
这一部分讲任务执行的条件的设置。
// todo:这里和我们的需求不符合,之后再看。
给任务加TAG
就是一个集中处理,可以理解成微信好友的分组orz
重复性任务
其实这里和前面的典型的工作流程差不多,不过由于前面没有讲述,所以这里具体描述一下过程。
- 首先创建一个继承自Worker的类:
public class MyFileWorker extends Worker { // 自定义你自己的Worker }
- Worker是一个抽线类,所以我们首先要实现必须要实现的方法:
public class MyFileWorker extends Worker { public MyFileWorker( @NonNull Context context, @NonNull WorkerParameters params) { super(context, params); } @Override public Worker.Result doWork() { //todo: 添加你自己的任务 return Result.SUCCESS; // 返回Result.SUCCESS表示任务成功执行。 // 返回Result.FAILUER表示任务执行失败但是不用重试。 // 返回Result.RETRY表示任务执行失败稍后重试。 } }
- 这里贴一下我的Worker的最终效果:
import android.content.Context; import android.support.annotation.NonNull; import java.io.File; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; import androidx.work.Worker; import androidx.work.WorkerParameters; public class MyFileWorker extends Worker { public MyFileWorker( @NonNull Context context, @NonNull WorkerParameters params) { super(context, params); } @Override public Worker.Result doWork() { boolean isWriteFileSuccessful = testWriteIntoFile(); if(isWriteFileSuccessful) return Result.SUCCESS; else return Result.RETRY; // (Returning RETRY tells WorkManager to try this task again // later; FAILURE says not to try again.) } /** * 一个向文件内写入的函数,成功返回true,失败返回false */ private boolean testWriteIntoFile() { try{ File file = new File("/storage/emulated/0/1/testBackground.txt"); FileOutputStream fos = new FileOutputStream(file, true); // 向文件内追加写入 SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd--HH时mm分ss秒SSS"); String content = "WorkManager的测试内容。在时间:" + formatter.format(new Date()) + "打印完成\n"; byte [] bytes = content.getBytes(); fos.write(bytes); fos.close(); return true; } catch(Exception e){ e.printStackTrace(); return true; } } }
就是个简单的向文件中写日志的功能。
- 在主界面添加一个按钮,按钮的回调是周期性调用Work。具体代码如下:
private void initView() { ... findViewById(R.id.btWorkManager).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { doBackgroundJobWithWorkManager(); } }); } private void doBackgroundJobWithWorkManager() { PeriodicWorkRequest.Builder fileWritingBuilder = new PeriodicWorkRequest.Builder(MyFileWorker.class, 15, TimeUnit.MINUTES); // 这里要注意15min是限制的最短时间了,具体可以查看Builder函数的注释。 // Create the actual work object: PeriodicWorkRequest fileWritingWork = fileWritingBuilder.build(); // Then enqueue the recurring task: WorkManager.getInstance().enqueue(fileWritingWork); SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd--HH时mm分ss秒SSS"); try { File file = new File("/storage/emulated/0/1/testBackground.txt"); FileOutputStream fos = new FileOutputStream(file, true); String content = "开始WorkManager。在时间" + formatter.format(new Date()) + "打印完成\n"; byte [] bytes = content.getBytes(); fos.write(bytes); fos.close(); } catch (IOException e) { e.printStackTrace(); } mTvResult.append("这是WorkManager" + formatter.format(new Date())+ "\n"); }
准备完成,开始调试————我在10月12日15:40:45 122毫秒的时间点击了按钮开始测试WorkManager。不出意外的话十五分钟左右之后文件内会追加第一行信息,如果成功我会清空后台,看看之后会不会出现。
(要指明的是,在我点击了开始任务的时间之后大概一秒钟之内,在15:40:45 239秒就写入了第一行测试内容。现在文件大小是2.98kb)15:56:55 335毫秒,打印了第二次日志。
16:10:45 278毫秒,打印了第三次日志。
现在我们关闭后台程序。
16:27 文件还是没有变化,估计是出了问题或者干脆不可行。
16:34 在查看其他文档的同时将APP开启,顺便检测一下是否会重新开始运行。
结果16:34:07 324毫秒就打印了第四次日志。
16:48 再次关闭APP
16:52 还未打印出日志,打开APP
16:52:16 498马上打印出了第五次日志。16:59,对APP做了少许修改,然后点击运行(不知道这样会不会终止任务?)。
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
17:07:46 692毫秒,打印出第六次日志(但是要注意的是这里我对MyFileWorker类做了一些修改,让它打印出的内容是包含ID的,结果打印出了新的内容【我并没有点击新建WorkManager的按钮,也就是说它还在执行旧的Work,只是执行的时候到程序的代码处去找工作内容的时候,获取到了新的工作内容。】)
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※↑↑↑↑↑↑↑这个发现也很重要,总之是证明了正常情况下重启APP还是会执行旧的WorkSequence↑↑↑↑↑
这里附上日志文件WorkManager部分的全部内容:
开始WorkManager。在时间2018/10/12--15时40分45秒120打印完成 WorkManager的测试内容。在时间:2018/10/12--15时40分45秒239打印完成 WorkManager的测试内容。在时间:2018/10/12--15时56分55秒335打印完成 WorkManager的测试内容。在时间:2018/10/12--16时10分45秒278打印完成 WorkManager的测试内容。在时间:2018/10/12--16时34分07秒234打印完成 WorkManager的测试内容。在时间:2018/10/12--16时52分16秒498打印完成 WorkManager,序列7949ca4a-b92e-4ffc-b8ab-db7eea3724b0的测试内容。在时间:2018/10/12--17时07分46秒692打印完成
参考简书博客-Android Jetpack - 使用 WorkManager 管理后台任务的**“保活?”**部分,原文内容是:
这里引入一个思考,既然 WorkManager 的生命力这么强,还可以实现定时任务,那能不能让我们的应用生命力也这么强?换句话说,能不能用它来保活?
要是上面有细看的话,你应该已经发现这几点了:
- 定时任务有最小间隔时间的限制,是 15 分钟
- 只有程序运行时,任务才会得到执行
- 无法拉起 Activity
总之,用 WorkManager 保活是不可能了,这辈子都不可能保活了。
其中第二点——“只有程序运行时,任务才会得到执行。”和我们观测到的情况相一致。
也就是说应该是很难做到即使关闭APP还是能够一直刷新的情况了……但是可以保证程序在后台也可以执行。并且关闭APP再启动的时候也不用重新发布任务。
总结:
- JobScheduler和WorkManager都只能在APP存活的时候执行,但是定时器是一直工作的。
- 关闭APP再启动,JobScheduler并不能够直接继续运行,但是WorkManager可以。
- 如果重启APP的时候,WorkManager任务的计时器应该已经执行了一次或多次,则会立即开始执行。
- 重启App之后WorkManager如果直接执行了一个任务,则从这个时候开始算新的周期,不会按旧有周期走。
参考: (JobScheduler部分)
https://www.jianshu.com/p/1f2103d3d2a2
https://blog.csdn.net/allisonchen/article/details/79218713
https://developer.android.com/reference/android/app/job/JobScheduler参考:(WorkManager部分)
https://www.jianshu.com/p/e495ee6e84de作者:任冉rr
链接:https://www.jianshu.com/p/b12a1163c4c2 -
定时任务的开启关闭
2020-01-03 15:46:17定时任务的开启关闭 思路:(了解ThreadPoolTaskScheduler这个类,TaskScheduler...1、ThreadPoolTaskScheduler 实现TaskScheduler,可以通过方法 schedule(java.lang.Runnable task, Trigger trigger),添加定时任... -
java计划任务、逾期自动关闭等功能
2018-01-16 16:51:23一:计划任务、逾期自动关闭等功能 spring中配置文件: 计划任务配置,用 @Service @Lazy(false)标注类,用@...task:executor id="executor" pool-size="10"/> task:scheduler id="scheduler" pool-size="1 -
实战 - LTS服务关闭
2017-06-30 11:22:49light-task-scheduler (LTS) 国内开源的分布式作业调度系统。主要用于解决分布式任务调度问题,支持实时任务,定时任务和Cron任务。请大家一起支持国产开源。 LTS的安装部署,请参见另一篇博客:实战-LTS安装部署 -
如何关闭任务计划
2009-07-30 22:43:00如下图,在将名为Task Scheduler 服务改为已禁用,选择停止2。删除c:\windows\tasks文件夹,建一个新的tasks文件夹,然后将此文件夹的安全性设为禁止存取,包括本机管理员,这样,就彻底关闭了任务计划的共享。 转载... -
事件计划自动关闭_Windows 10任务计划程序为您提供了更多功能
2020-11-22 20:39:00本文详细介绍了最新版本的Task Scheduler与旧版本的区别。什么是任务计划程序?Windows 10 Task Scheduler 在特定 时间或某些事件后(我们将其称为触发器或条件)执行 脚本或程序。它作为维护或自动化工具很有用,但在... -
更新以列入计划 关闭所有vs窗口后开始执行修改_自定义属性批量修改应该怎么做呢?...
2020-12-06 09:43:09要批量修改自定义属性,需要用到批量处理工具,在SolidWorks中的批量处理工具是:SOLIDWORKS Task Scheduler。SOLIDWORKS Task Scheduler,可让您设置将来执行的任务。包括转换文件、更新文件、打印文件等等,今天... -
安排季度代码运行 - PHP [关闭]
2014-10-14 13:27:19<p>I have a ... I found ways to utilize Windows Task Scheduler , but in the scheduling triggering options, there is no <em>Quarterly</em> option. Thanks in advance for any help :) </div> -
Php关闭窗口x经过一段时间后
2013-04-30 19:35:25Is there a way to do it in php? Or if anyone knows how to do it in windows task scheduler, that would be good too. <p>Anytime I searched for it on google, all that popped up was the javascript way ... -
mysql 自动维护任务_彻底关闭Windows Server 2012 R2的自动维护任务
2021-03-03 21:44:15Step 1 由于自动维护任务为系统级的权限...具体做法如下:C:\Windows\System32\Tasks\Microsoft\Windows\TaskScheduler\Maintenance configurator属性 --安全-- 高级--所有者,将administrator设置为所有者。Step 2 ... -
关闭win8及win8.1的自动维护
2014-02-23 13:05:22首先进入文件夹C:\Windows\System32\Tasks\Microsoft\Windows\TaskScheduler; 在文件Maintenance Configurator上右键菜单-属性,定位到“安全”,并点击高级按钮 点击“更改” 输入新用户名“Administrators... -
彻底关闭Windows Server 2012 R2的自动维护任务
2013-12-10 17:41:38Step 1 由于自动维护任务为系统级的权限,因此默认情况下,无法完全...具体做法如下: C:\Windows\System32\Tasks\Microsoft\Windows\TaskScheduler\Maintenance configurator 属性 --安全-- 高级--所有者,将admin... -
设置IIS服务器定时自动重启的方法
2019-10-02 16:12:271、首先开启Windows的任务计划服务Task Scheduler,如果你没有关闭该服务的话,默认是开启的;如果你关闭了该服务,那开启Task Scheduler服务方法如下: 开始→设置→控制面板→管理工具→服务→在右边的窗口中... -
mysql 定时任务
2017-08-25 17:23:00//开启event_scheduler4、关闭事件 alter event event_task_payment ON COMPLETION PRESERVE DISABLE;5、开启事件alter event event_task_payment ON COMPLETION PRESERVE ENABLE;6 删除DROP EVE... -
设置IIS自动重启
2011-03-04 13:48:00设置IIS服务器定时自动重启的方法2010年06月29日 星期二 上午 08:16设置IIS服务器定时自动重启的方法: 1、首先开启Windows的任务计划服务Task Scheduler,如果你没有关闭该服务的话,默认是开启的;... -
Windows 2003 Server安全配置完整篇(二)
2019-10-04 00:59:42二.关闭不需要的服务 打开相应的审核策略 ... Task scheduler 允许程序在指定时间运行 Messenger 传输客户端和服务器之间的 NET SEND 和 警报器服务消息 Distributed File System: 局域网管理共享文件... -
mysql
2020-11-29 12:56:07-- 创建事件 CREATE EVENT IF NOT EXISTS event_task_status_update ON SCHEDULE EVERY 1 DAY ON COMPLETION PRESERVE ...SET GLOBAL event_scheduler = 1; --开启事件 0-关闭 show variables like 'e.. -
Windows2003服务器安全策略
2012-12-09 19:01:26策略一:关闭windows2003不必要的服务 ·Computer Browser 维护网络上计算机的... ·Task scheduler 允许程序在指定时间运行 ·Routing and Remote Access 在局域网以及广域网环境中为企业提供路由服务 ... -
【如何使自己的服务器更安全?】
2013-08-08 11:21:10【策略一】:关闭不必要的服务 ·computerbrowser 维护网络上计算机的最新列表以及提供这个列表 ·taskscheduler 允许程序在指定时间运行 ·routing andremote access 在局域网以及广域网环境中为企业提供路由... -
windows 2003中IIS6的安全配置
2021-01-20 16:15:54IIS安全配置主要有3个方面需要注意 设置主目录权限 删除不需要的扩展名映射 删除危险的IIS组件 ... 关闭不必要的服务,服务开的多不是好事,将不必要的服务通通...Task scheduler:允许程序在指定时间运行 Routing and Re -
MySQL --- MySQL的定时器和存储过程
2017-03-31 13:50:071、数据库是否开启定时器 -- 查看是否开启定时器 ...0或者off 表示关闭 1或者on表示开启 SET GLOBAL event_scheduler = 1; 2、创建表 -- 创建备份表 CREATE TABLE `task_count_copy` ( `uuid` -
Spring Scheduled定时任务动态修改cron参数
2020-04-13 12:04:28对于这种需求, 可以利用TaskScheduler借口来实现,实现方法有两种 启动定时,关闭定时,使用新参数启动定时 使用自定义的Trigger启动定时,更改参数 范例代码如下 1 2 3 4...