我在Xamarin Android中有后台服务,但问题是我无法将其用作Async
方法,它会出错。
返回类型必须是'StartCommandResult'才能匹配重写成员'Service.OnStartCommand(Intent,StartCommandFlags,int)
实际重写的方法是void
但是要使用await我必须将其更改为async Task<T>
,然后它会产生错误。我到处搜索,但找不到合适的解决方案。
整个班级的代码段在这里:
{
[Service(IsolatedProcess = false, Enabled = true, Label = "BackgroundNotificationService")]
class BackgroundNotificationService : Service
{
static readonly string TAG = "X:" + typeof(BackgroundNotificationService).Name;
static readonly int TimerWait = 3600000;
Timer timer;
DateTime startTime;
bool isStarted = false;
public override IBinder OnBind(Intent intent)
{
return null;
}
public override void OnCreate()
{
base.OnCreate();
}
public override void OnDestroy()
{
timer.Dispose();
timer = null;
isStarted = false;
TimeSpan runtime = DateTime.UtcNow.Subtract(startTime);
Log.Info(TAG, $"Simple Service destroyed at {DateTime.UtcNow} after running for {runtime:c}.");
base.OnDestroy();
}
public override async Task<StartCommandResult> OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
StartCommandResult a = StartCommandResult.NotSticky;
Log.Debug(TAG, $"OnStartCommand called at {startTime}, flags={flags}, startid={startId}");
if (isStarted)
{
TimeSpan runtime = DateTime.UtcNow.Subtract(startTime);
Log.Info(TAG, $"This service was already started, it's been running for {runtime:c}.");
await UpdateData();
}
else
{
startTime = DateTime.UtcNow;
Log.Info(TAG, $"Starting the service, at {startTime}.");
timer = new Timer(HandleTimerCallback, startTime, 0, TimerWait);
isStarted = true;
await UpdateData();
}
return a;
}
void HandleTimerCallback(object state)
{
TimeSpan runTime = DateTime.UtcNow.Subtract(startTime);
Log.Info(TAG, $"This service has been running for {runTime:c} (since ${state}).");
}
}
}
据我所知它应该有效,因为我在覆盖方法中返回StartCommandResult
。但如果我错了,那么有什么方法可以让我失踪吗?也许有另一种方法可以做到这一点,我不知道。
更新和解决方案
我最终实现了另一个新的IntentService
类来完成所有后台更新工作,而上述服务只处理IntentService
的调用。与其他任何服务一样,该服务具有明确的意图。
public class CustomIntentService : IntentService
{
public CustomIntentService() : base("CustomIntentService")
{
}
protected override async void OnHandleIntent(Intent intent)
{
// do your work
string servicename = typeof(CustomIntentService).Name;
Log.Info(servicename, "Starting background work");
try
{
await UpdateData();
}
catch (Exception ex)
{
Log.Info(servicename, "Background work returned with errors.\nError:" + ex.Message);
return;
}
Log.Info(servicename, "Background work completed without errors.");
}
}
答案 0 :(得分:0)
这是因为基类OnStartCommand
中定义的方法Service
的返回类型为StartCommandResult
而不是Task<StartCommandResult>
,因此在覆盖时无法更改方法的retirn类型在儿童班。
如果要将其设置为异步,则可以创建代理方法,如:
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
return OnStartCommandAsync(intent,flags,startId).Result;
}
,async方法就像:
private async Task<StartCommandResult> OnStartCommandAsync(Intent intent, StartCommandFlags flags, int startId)
{
StartCommandResult a = StartCommandResult.NotSticky;
Log.Debug(TAG, $"OnStartCommand called at {startTime}, flags={flags}, startid={startId}");
if (isStarted)
{
TimeSpan runtime = DateTime.UtcNow.Subtract(startTime);
Log.Info(TAG, $"This service was already started, it's been running for {runtime:c}.");
await UpdateData();
}
else
{
startTime = DateTime.UtcNow;
Log.Info(TAG, $"Starting the service, at {startTime}.");
timer = new Timer(HandleTimerCallback, startTime, 0, TimerWait);
isStarted = true;
await UpdateData();
}
return a;
}
但请注意,它不会为您提供所需的目的,因为.Result
将阻塞该线程,直到async
方法返回结果,因此它基本上是同步的异步方法< / p>
供参考see this post。