在我的 .NET Maui Android 应用程序中,我正在尝试使用
AndroidX.Work.Worker
来启动一个长时间运行的进程,该进程侦听来自加速度计的事件。我遇到的问题是,一旦 DoWork
方法退出,Worker 就会终止。所以我需要通过防止 DoWork
退出来保持 Worker 运行,但无法弄清楚代码。
public class DropDetectorWorker : AndroidX.Work.Worker
{
public override Result DoWork()
{
CreateInitialNotificationChannel();
var foregroundInfo = new ForegroundInfo(NotificationId++, BuildInitialNotification());
SetForegroundAsync(foregroundInfo);
InitialiseDropDetector();
// TODO - prevent DoWork from exiting
return Result.InvokeSuccess();
}
private void InitialiseDropDetector()
{
_dropDetector.DropDetected += DropDetector_DropDetected;
_dropDetector.Start();
}
private void DropDetector_DropDetected(object sender, DropDetectedEventArgs e)
{
_lastDropDetected = SystemDate.UtcNow;
TriggerAutoclaimNotification(e.Magnitude);
}
private void CreateInitialNotificationChannel()
{
NotificationChannel channel = new(INITIAL_NOTIFICATION_CHANNEL_ID, INITIAL_NOTIFICATION_CHANNEL_NAME, NotificationImportance.Default)
{
LightColor = Microsoft.Maui.Graphics.Color.FromRgba(0, 0, 255, 0).ToInt(),
LockscreenVisibility = NotificationVisibility.Public
};
_notificationManager.CreateNotificationChannel(channel);
}
private void TriggerAutoclaimNotification(double magnitude)
{
var foregroundInfo = new ForegroundInfo(NotificationId, BuildMakeClaimNotification(magnitude));
SetForegroundAsync(foregroundInfo);
}
}
你的问题是关于如何启动一个长期运行的、事件驱动的任务。
是否可以在您的
DropDetectorWorker
构造函数中采用和使用阻止任务完成的相同方法?我会展示我的想法,这可能适合也可能不适合。
此示例为了演示目的而保持简单。此类任务的一个干净、最小的示例是一个时钟更新程序,它(不阻塞 UI 线程)对当前时间进行大约每秒 10 倍的采样,并在秒数发生变化时触发一个事件。此代码片段显示了如何在
App
构造函数中启动此任务,让它在后台运行。
这种通用方法可以很容易地适应您希望应用程序执行的加速度计监控。
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
_ = Task.Run(() => longRunningEventDrivenTask(LongRunningTskCanceller.Token));
}
CancellationTokenSource LongRunningTskCanceller { get; } = new CancellationTokenSource();
private async Task longRunningEventDrivenTask(CancellationToken token)
{
int prevSecond = -1;
while(!token.IsCancellationRequested)
{
var now = DateTime.Now;
if (now.Second != prevSecond)
{
OnSecondChanged(new SecondChangedEventArgs(timestamp: now));
prevSecond= now.Second;
}
await Task.Delay(TimeSpan.FromSeconds(0.1), token);
}
}
public event SecondChangedEventHandler SecondChanged;
protected virtual void OnSecondChanged(SecondChangedEventArgs e)
{
SecondChanged?.Invoke(this, e);
}
}
活动
public delegate void SecondChangedEventHandler(Object sender, SecondChangedEventArgs e);
public class SecondChangedEventArgs : EventArgs
{
public SecondChangedEventArgs(DateTime timestamp)
{
Timestamp = timestamp;
}
public DateTime Timestamp { get; }
}