As I pointed out in my previous post a common scenario for custom apis in a Mobile Service is to hand off tasks that aren’t easily done on a mobile device, or are better suited to being done server side (eg report creation). Quite often these tasks can take longer than the default timeout of most service requests (typically 60seconds) which means the mobile app ends up raising an exception which is not very useful. A better approach is to queue the work somehow and then to periodically check on it’s progress. In this post I’m just going to demonstrate one way to allow the service to respond immediately, whilst continuing to carry out the task in the background. Note that the ReportHost is based on the JobHost class described in Phil Haack’s post on the dangers of background tasks
public async Task<string> Get()
{
var host = new ReportHost();
host.DoWork(async (cancel) =>
{
try
{
await Task.Delay(TimeSpan.FromMinutes(2), cancel);
}
catch (Exception ex)
{
// Don’t bubble the exception – do something sensible here!
Debug.WriteLine(ex.Message);
}
});
Services.Log.Info(“Hello from custom controller!”);
return “Hello”;
}
And the ReportHost class
public class ReportHost : IRegisteredObject
{
private readonly ManualResetEvent reportLock = new ManualResetEvent(false);
private readonly CancellationTokenSource cancellation=new CancellationTokenSource();public ReportHost()
{
HostingEnvironment.RegisterObject(this);
}public void Stop(bool immediate)
{
cancellation.Cancel();
reportLock.WaitOne();
HostingEnvironment.UnregisterObject(this);
}public void DoWork(Func<CancellationToken,Task> work)
{
Task.Run(async () =>
{
await work(cancellation.Token);
reportLock.Set();
});
}
}
I haven’t shown any client side code for the timebeing because it remains the same (although it won’t timeout now!). The next step is to provide some way that the client can check on the progress of the work item.