.NET Maui Android中Worker.DoWork如何维持事件驱动长时任务运行
问题与解决方案:AndroidX.Work.Worker维持长时加速度计监听
问题场景
在.NET Maui Android应用中,使用AndroidX.Work.Worker启动监听加速度计事件的长时进程,当前遇到的问题是:一旦DoWork方法退出,Worker就会终止,需要通过阻止DoWork退出来维持Worker运行。
解决方案代码
修改DropDetectorWorker类,通过ManualResetEventSlim阻塞DoWork方法,直到主动触发停止信号或Worker被系统终止:
using System.Threading; public class DropDetectorWorker : AndroidX.Work.Worker { private readonly ManualResetEventSlim _waitEvent = new ManualResetEventSlim(false); private readonly DropDetector _dropDetector = new DropDetector(); private NotificationManager _notificationManager; private const string INITIAL_NOTIFICATION_CHANNEL_ID = "drop_detector_channel"; private const string INITIAL_NOTIFICATION_CHANNEL_NAME = "Drop Detector"; private static int NotificationId = 1001; public DropDetectorWorker(Context context, WorkerParameters workerParams) : base(context, workerParams) { _notificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService); } public override Result DoWork() { CreateInitialNotificationChannel(); var foregroundInfo = new ForegroundInfo(NotificationId++, BuildInitialNotification()); SetForegroundAsync(foregroundInfo).Wait(); InitialiseDropDetector(); // 阻塞DoWork方法,直到_waitEvent被触发 _waitEvent.Wait(); // 清理资源 _dropDetector.DropDetected -= DropDetector_DropDetected; _dropDetector.Stop(); return Result.InvokeSuccess(); } private void InitialiseDropDetector() { _dropDetector.DropDetected += DropDetector_DropDetected; _dropDetector.Start(); } private void DropDetector_DropDetected(object sender, DropDetectedEventArgs e) { var lastDropDetected = DateTime.UtcNow; TriggerAutoclaimNotification(e.Magnitude); // 若需在某次检测后停止Worker,可在此调用:_waitEvent.Set(); } private void CreateInitialNotificationChannel() { if (_notificationManager.GetNotificationChannel(INITIAL_NOTIFICATION_CHANNEL_ID) != null) return; NotificationChannel channel = new(INITIAL_NOTIFICATION_CHANNEL_ID, INITIAL_NOTIFICATION_CHANNEL_NAME, NotificationImportance.Default) { LightColor = Microsoft.Maui.Graphics.Color.FromRgba(0, 0, 255, 255).ToInt(), LockscreenVisibility = NotificationVisibility.Public }; _notificationManager.CreateNotificationChannel(channel); } private Notification BuildInitialNotification() { return new Notification.Builder(Context, INITIAL_NOTIFICATION_CHANNEL_ID) .SetContentTitle("Drop Detector Running") .SetContentText("Listening for drop events") .SetSmallIcon(Resource.Drawable.ic_notification) .Build(); } private Notification BuildMakeClaimNotification(double magnitude) { return new Notification.Builder(Context, INITIAL_NOTIFICATION_CHANNEL_ID) .SetContentTitle("Drop Detected!") .SetContentText($"Magnitude: {magnitude:F2}") .SetSmallIcon(Resource.Drawable.ic_notification_alert) .Build(); } private void TriggerAutoclaimNotification(double magnitude) { var foregroundInfo = new ForegroundInfo(NotificationId++, BuildMakeClaimNotification(magnitude)); SetForegroundAsync(foregroundInfo).Wait(); } public override void OnStopped() { // 系统停止Worker时,触发信号解除阻塞 _waitEvent.Set(); base.OnStopped(); } }
关键说明
- 用
ManualResetEventSlim实现阻塞:DoWork末尾调用_waitEvent.Wait(),会一直阻塞直到_waitEvent.Set()被触发。 - 处理系统终止场景:重写
OnStopped方法,当系统主动停止Worker时,触发信号让DoWork退出并清理资源。 - 资源清理:退出前移除事件订阅、停止检测器,避免内存泄漏。
- 前台服务确保稳定:调用
SetForegroundAsync时用.Wait(),保证前台服务设置完成后再启动监听。 - 按需停止Worker:如果需要在某次掉落检测后终止任务,可在
DropDetector_DropDetected事件中调用_waitEvent.Set()。
内容的提问来源于stack exchange,提问作者Netricity
相关产品推荐
相关产品推荐

