Add support for hosted services in .NET MAUI apps
Look into using hosted services. This would replace the icky IMauiInitializeService that was added in https://github.com/dotnet/maui/pull/2137, and also to enable users to use hosted services. MAUI will automatically call StartAsync/StopAsync at the appropriate time. Sadly, this pattern is async-only, whereas in MAUI the call sites are always (or at least almost always) sync. But given that this is app startup/shutdown, doing async-over-sync might be OK (we would block).
This is a follow-up to PR https://github.com/dotnet/maui/pull/2137.
Other notes:
- Need to consider this when implementing: https://github.com/dotnet/aspnetcore/pull/36122
But given that this is app startup/shutdown, doing async-over-sync might be OK (we would block).
I think this is reasonable. That's effectively what happens when a Program.Main() uses the generic host. Even with an async Program.Main(), the compiler synthesizes the real entry point which blocks.
Just to clarify my understanding, this would mean once supported i could drop the following icky code I'm using? I pass the IHostEnvironment environment to some wiring code, The maui App assembly is just "HeroesProfile", but i use shared IoC registration. To give some context on how I'm using DI.
/*
* Hosted services only works with the Hosting Extensions from .NET
* Maui does not use the same Hosting service and so we much register them differently depending on how we execute background services.
* If this is for Maui, we must hook into Application startup and run the services.
* If this is for Console, .AddHostedService will handle starting the services for us.
*/
if (environment.ApplicationName.Equals("HeroesProfile.Console"))
{
services
.AddHostedService<GameSimulator>()
.AddHostedService<FileWatchers>()
.AddHostedService<OnLaunchReplayProcessor>();
}
else
{
services
.AddSingleton<GameSimulator>()
.AddSingleton<FileWatchers>()
.AddSingleton<OnLaunchReplayProcessor>();
}
@pjmagee yeah I think so. If we implement this, there would be proper support for hosted services so all the regular APIs that exist for that would work as expected (starting/stopping those services).
Dumb question hopefully not too off-topic; what does an IHostedService mean on Android? Will that behave like an Android foreground service or will it only live as long as the MAUI app is running? I want to run an always-on .NET 5 BackgroundService on my Android smartphone and am a little lost figuring out how to utilize MAUI or net6.0-android for that yet.
@RayKoopa - This would be for in-app in-proc services. So they would start when the app starts, and dies when the app dies. I'm not sure in Android terminology what that equates to, but it's not a background thing.
@Eilon Ah alright, I expected it to be "app-wide". I'll try to figure out how to host my Android foreground service then (which is like a "system-wide" background thread with a notification, that has no connection to an app or UI once started). Thanks for the fast reply!
Any news from this issue?
@Eilon Added pull request for this issue https://github.com/dotnet/maui/pull/3718
@hflexgrig oh wow I'll take a look!
@Eilon deleted old one and create new https://github.com/dotnet/maui/pull/3724
any status on this feature? Thanks
will there ever be hosted services?
FWIW, having native IHostedService support would allow OpenIddict users to use the new OpenIddict.Client.SystemIntegration package on MAUI/WinUI. I posted more information here: https://github.com/openiddict/openiddict-core/pull/1480#issuecomment-1397746558.
This kind of addition would definitely make it easier to work with an abstracted service model instead of platform specific service implementations.
Any news about this? Currently stuck because of this...
This work is not currently planned. Could you manually start the services in MauiProgram or another part of the app? Certainly not ideal, but it could be a reasonable workaround.
This work is not currently planned. Could you manually start the services in
MauiProgramor another part of the app? Certainly not ideal, but it could be a reasonable workaround.
Does this really work in Android when screen is switched off?
Any updates?
Need this
I'm also looking forward to seeing it in MAUI. In the meantime, what is the best practice for MAUI to have background tasks that periodically perform REST requests to get data?
I'm also looking forward to seeing it in MAUI. In the meantime, what is the best practice for MAUI to have background tasks that periodically perform REST requests to get data?
I think you can take the concept of a hosted service but you need to activate those in the Maui Startup event. that's basically the best workaround we have, not sure the impact on different devices though.
Hosted services will run while the app is active in the foreground only, right?
I'm also looking forward to seeing it in MAUI. In the meantime, what is the best practice for MAUI to have background tasks that periodically perform REST requests to get data?
I use a singleton service that initializes a dispatcher timer on a certain interval, which is wired up in the constructor of the service.
A hosted service would be better, for a number of reasons. But that is adequate-ish.
i.e.
.AddSingleton<ISyncService, SyncService>()
and
internal sealed class SyncService : ISyncService, IDisposable
{
private readonly IDispatcherTimer syncTimer;
public SyncService()
{
// Set a timer to execute the sync on an interval
this.syncTimer = Application.Current.Dispatcher.CreateTimer();
this.syncTimer.Interval = TimeSpan.FromMinutes(2);
this.syncTimer.Tick += this.OnSyncTimerElapsed;
}
private void OnSyncTimerElapsed(object? sender, EventArgs e)
{
// Do Stuff Here
}
}
Any update?
Any update?
You can grab this file and register it as HostedService:
builder.Services.AddSingleton<HostedServiceExecutor>();
Then just before returning app, you can call it
using (var scope = app.Services.CreateScope())
{
var hsExecutor = scope.ServiceProvider.GetRequiredService<HostedServiceExecutor>();
hsExecutor.StartAsync(default).GetAwaiter().GetResult();
}
return app;
After that it start all your Hosted/Background services.