.NET MAUI中WorkManager后台运行数小时后停止工作
.NET MAUI中WorkManager后台任务运行数小时后停止的问题
我在.NET MAUI中通过以下代码实现了WorkManager,将其配置为每30分钟执行一次后台任务。但成功运行约5-6小时后,任务不再按指定间隔触发,完全停止工作。请问代码是否存在问题?我是否遗漏了某些配置?
实现代码
using Android.App.Job; using Android.Content; using Android.Runtime; using AndroidX.Work; public class BackgroundWork : Worker { public BackgroundWork(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { } public BackgroundWork(Context context, WorkerParameters workerParams) : base(context, workerParams) { } public override Result DoWork() { //Analytics.TrackEvent("DoWork called.."+ DeviceInfo.Name); bool bResult = AlarmHelper.SetAlarms(); if (bResult) return Result.InvokeSuccess(); else return Result.InvokeFailure(); } public override void OnStopped() { //Logger.LogEvent("BackgroundWork OnStopped"); base.OnStopped(); } } using AndroidX.Work; public class MainActivity : MauiAppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); #if __ANDROID__ using var builder = new Constraints.Builder(); builder.SetRequiredNetworkType(AndroidX.Work.NetworkType.Connected); var workConstraints = builder.Build(); var interval = TimeSpan.FromMinutes(30); SetupWorker<BackgroundWork>(interval, workConstraints); #endif } private void SetupWorker<TWorker>(TimeSpan interval, Constraints workConstraints) where TWorker : Worker { var request = PeriodicWorkRequest.Builder.From<TWorker>(interval) .SetConstraints(workConstraints) .Build(); WorkManager.GetInstance(ApplicationContext) .EnqueueUniquePeriodicWork(nameof(TWorker), ExistingPeriodicWorkPolicy.Replace, request); } }
运行日志
Starting logging at 6/12/2023 6:44:25 PM 6/12/2023 6:44:28 PM : Bday Reminder Start. 6/12/2023 6:44:32 PM : Done -- Reminders.0 6/12/2023 6:45:16 PM : Today Reminder Start. 6/12/2023 6:45:22 PM : Done -- Reminders.0 6/12/2023 7:09:32 PM : PopulateDayChange -- called -> 6/12/2023 7:09:31 PM 6/13/2023 12:58:15 PM : PopulateDayChange -- called -> 6/13/2023 12:58:15 PM 6/13/2023 12:58:15 PM : Populate Day Change -- day change happened -> 6/13/2023 12:58:15 PM 6/13/2023 12:58:15 PM : Populate Day Change -- day change happened -> 6/13/2023 12:58:15 PM 6/13/2023 12:58:24 PM : --- Done -- 6/13/2023 12:58:24 PM 6/13/2023 6:42:00 PM : PopulateDayChange -- called -> 6/13/2023 6:41:59 PM 6/13/2023 6:42:00 PM : PopulateDayChange -- called -> 6/13/2023 6:41:59 PM 6/13/2023 6:44:05 PM : PopulateDayChange -- called -> 6/13/2023 6:44:05 PM 6/13/2023 6:45:00 PM : Today Reminder Start. 6/13/2023 6:45:00 PM : Done -- Reminders.2 6/13/2023 6:47:59 PM : PopulateDayChange -- called -> 6/13/2023 6:47:59 PM 6/13/2023 6:50:30 PM : PopulateDayChange -- called -> 6/13/2023 6:50:30 PM 6/14/2023 3:20:46 PM : PopulateDayChange -- called -> 6/14/2023 3:20:46 PM 6/14/2023 3:20:46 PM : Populate Day Change -- day change happened -> 6/14/2023 3:20:46 PM 6/14/2023 3:20:46 PM : Populate Day Change -- day change happened -> 6/14/2023 3:20:46 PM 6/14/2023 3:20:58 PM : --- Done -- 6/14/2023 3:20:58 PM 6/14/2023 3:50:47 PM : PopulateDayChange -- called -> 6/14/2023 3:50:47 PM 6/14/2023 4:20:47 PM : PopulateDayChange -- called -> 6/14/2023 4:20:47 PM 6/14/2023 4:50:48 PM : PopulateDayChange -- called -> 6/14/2023 4:50:48 PM 6/14/2023 5:20:48 PM : PopulateDayChange -- called -> 6/14/2023 5:20:48 PM 6/14/2023 5:50:48 PM : PopulateDayChange -- called -> 6/14/2023 5:50:48 PM 6/14/2023 6:20:48 PM : PopulateDayChange -- called -> 6/14/2023 6:20:48 PM 6/14/2023 6:44:00 PM : Bday Reminder Start. 6/14/2023 6:44:01 PM : Done -- Reminders.0 6/14/2023 6:45:00 PM : Today Reminder Start. 6/14/2023 6:45:01 PM : Done -- Reminders.2 6/14/2023 6:50:49 PM : PopulateDayChange -- called -> 6/14/2023 6:50:49 PM 6/14/2023 7:20:49 PM : PopulateDayChange -- called -> 6/14/2023 7:20:49 PM 6/15/2023 11:08:06 AM : PopulateDayChange -- called -> 6/15/2023 11:08:06 AM 6/15/2023 11:08:06 AM : Populate Day Change -- day change happened -> 6/15/2023 11:08:06 AM 6/15/2023 11:08:08 AM : --- Done -- 6/15/2023 11:08:08 AM 6/15/2023 11:38:08 AM : PopulateDayChange -- called -> 6/15/2023 11:38:08 AM 6/15/2023 12:08:08 PM : PopulateDayChange -- called -> 6/15/2023 12:08:08 PM 6/15/2023 12:47:09 PM : PopulateDayChange -- called -> 6/15/2023 12:47:09 PM 6/15/2023 1:17:09 PM : PopulateDayChange -- called -> 6/15/2023 1:17:09 PM
问题分析与解决方案
核心问题原因
- 系统电池优化节流:Android为延长续航,会对长时间运行的后台任务进行节流,即使使用WorkManager,数小时后也可能被降低执行频率或暂停,尤其是设备锁屏、低电量时。
- 网络约束限制:代码设置了
NetworkType.Connected,若设备长时间无网络,任务会被挂起,直到网络恢复。 - 重试策略缺失:当
DoWork返回失败时,WorkManager默认重试策略无法应对持续失败,可能导致任务停止调度。
针对性解决方案
- 增加调度灵活性:给任务添加弹性间隔,让系统有更多调度空间,降低被节流概率:
var request = PeriodicWorkRequest.Builder.From<BackgroundWork>(interval) .SetConstraints(workConstraints) .SetFlexInterval(TimeSpan.FromMinutes(10)) // 允许在周期最后10分钟内执行 .Build(); - 豁免电池优化:引导用户将应用加入电池优化白名单,避免系统完全暂停任务:
var intent = new Intent(Android.Provider.Settings.ActionRequestIgnoreBatteryOptimizations, Android.Net.Uri.Parse("package:" + PackageName)); StartActivity(intent); - 优化任务逻辑:确保
DoWork操作轻量化,避免长时间运行(单个WorkManager任务最长允许10分钟执行时间),若AlarmHelper.SetAlarms()逻辑复杂,考虑拆分任务。 - 添加状态监听:监听任务状态变化,记录停止原因以便排查:
WorkManager.GetInstance(ApplicationContext) .GetWorkInfosForUniqueWorkLiveData(nameof(BackgroundWork)) .Observe(this, workInfos => { foreach (var info in workInfos) { // 记录info.State(如Enqueued、Running、Failed、Cancelled等状态) } }); - 配置重试策略:针对任务失败场景,添加指数退避重试配置:
var request = PeriodicWorkRequest.Builder.From<BackgroundWork>(interval) .SetConstraints(workConstraints) .SetBackoffCriteria(BackoffPolicy.Exponential, TimeSpan.FromMinutes(5)) .Build();
内容的提问来源于stack exchange,提问作者Sunil Parmar
相关产品推荐
相关产品推荐

