Does anyone know if I have to manually dispose the dependency injection container which is used in Prism.Forms when the app (Xamarin Android) is terminated?
The problem:
I register a singleton service in Prism.Forms' RegisterServices method. The singleton service itself subscribes to some classic .NET events (+=) and implements IDisposable which is used to unsubscribe (-=) the mentioned events. So far so good. Everything works fine.
When I start the Android part of the Xamarin.Forms app, then go back (Android back button) so that the app is closed again, launch the app again --> it results in multiple event subscriptions. Dispose is never run anywhere, thus, no event unsubscribes are done in the singleton service. This ultimately leads to memory leaks.
Proposed solution (to be verified)
I override void OnDestroy method in MainActivity and from there I call App.Container.Dispose() so that Prims' DI container is disposed when the Android app is terminated. This disposable of the DI container leads to Dispose being called on the earlier mentioned singleton service.
What do you think? I've never seen anyone doing this, but it solves an essential problem. How would you solve this problem?
Related
Simple Injector documentation is quite clear on both transient and singleton registrations, and how they will be disposed etc. Docs indicate that singletons registered with all but the pre-constructed objects will get disposed when the container gets disposed.
My question specifically involves a singleton registration that I Need to be disposed when the ASP.NET application gets disposed (I send any remaining messages when that service is disposed). Most of my registrations are transient and get disposed when each request is disposed. When debugging in VS/IISExpress, I don't ever see when my singletons get disposed - or when the container itself ultimately gets disposed. In my console apps & azure services I simply call container.Dispose() when I'm done. Any clues in ASP.NET for this final cleanup?
For singletons to be disposed, you need to explicitly call Container.Dispose() when the application ends. This can be done for instance in the Application_End event in your Global.asax. But please be warned.
I send any remaining messages when that service is disposed
This seems like a very bad idea, because there are many reasons why an Application_End event doesn't run. IIS can quite aggressively kill applications, and so will do power outages and other hardware malfunctions. If that happens, it means that you will lose any messages that are still in the local buffer.
This might not be a problem for volatile messages that are used for application heartbeats and sometimes logging, but if those messages describe important business events, you should use durable queuing or storage mechanisms.
When debugging in VS/IISExpress, I don't ever see when my singletons get disposed
That can very well be. When debugging a web application, the web application never stops by itself. In case you stop debugging either the application is abruptly stopped without having a chance to run any finalizers and clean-up methods, or when you stop debugging, the application keeps running in the background; which still means you won't see any clean-up happening.
I have Asp.Net Webforms application with entity framework. Application is built on the default web application from Visual Studio.
Application is configured so that ApplicationDbContext is created per Owin
Context (per request). I am not closing DbContext after every DB query because that way I won't leverage all the caching that EF provides
So I use given DbContext returned from current Owin Context. But I don't see any piece of code that is disposing given DbContext. Should I dispose given DbContext in the End_Request event handler? Or it is handled automagically? (I guess not)
DbContext instances should be disposed of (but you'll probably be OK
if they're not) DbContext implements IDisposable. Its instances should
therefore be disposed of as soon as they're not needed anymore. In
practice however, and unless you choose to explicitly manage the
database connection or transaction that the DbContext uses, not
calling DbContext.Dispose() won't cause any issues
as Diego Vega, a EF team member, explains
Do I always have to call Dispose() on my DbContext objects? Nope
From my experience I can add this: In the past I never worried about disposing the dbcontext and i never had any kind of problems. Lately I don't create it manually but i let my DI container instantiate it for me and dispose it when is time to dispose.
I created a service with a RESTful API in ASP.NET, hosted in IIS. Inside this service, I would like to create an actor system with Akka.NET.
Upon creating the actor system:
var actorSystem = ActorSystem.Create("myActorSystem");
The following exception is thrown:
A first chance exception of type 'System.InvalidOperationException' occurred in System.Web.dll
Additional information: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%# Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.
The actor system is inherently a concurrent system with asynchronous messages being exchanged between actors. As explained here, this actor system would not survive IIS taking down the AppDomain, which is probably why the aforementioned exception is thrown.
This article explains how to run background tasks in ASP.NET. However, I don't see how I could use this for my actor system, as I have no control over the lifecycle of background tasks that might be created by Akka.NET.
Is there a way to make this work, or should I abandon the idea of having an actor system in an ASP.NET application?
EDIT: I also saw a question on Stackoverflow about implementing a REST service using Akka. Any advice about a solution similar to the Spray toolkit, but working for Akka.NET would be welcome.
I've used Akka.NET and Akka.Remote inside ASP.NET MVC applications that are doing up to 1000 requests per second on EC2 - so I'll share some of the tips and tricks I used to get it up and running successfully. Had a prototype version that even used Akka.Cluster but ended up not shipping that version.
Best place to call ActorSystem.Create is inside Global.asax Application_Start().
Hang onto a static reference to the ActorSystem object inside Global.asax itself, using a static field or property. Helps ensure that the ActorSystem itself doesn't get garbage-collected in long-running applications.
Create a separate static helper class to initialize any top-level actors your applications needs - i.e. actors at the top of the /user/ hierarchy. This class should also provide actor paths that your ASP.MVC controllers and action methods can use for Tell and Ask operations.
Creating the ActorSystem is a bit of an expensive operation, because lots of system-level stuff gets fired up at once. It's definitely best to do this once at application startup and then just cache the result inside the Application class.
Creating individual actor instances is cheap - you should be able to do this no-problem inside ASP.NET MVC action methods. If you see this error come up again, please let us know what part in the request-handling process this error occurred and with which version of ASP.NET.
Edit: added some updated guidance for how to do this on ASP.NET Core
https://petabridge.com/blog/akkadotnet-aspnetcore/
Keep your ActorSystem as a shared property in some static class container - this way you may access it from the rest of your application. Actor system initialization/disposal can be done by:
Global.asax - use ActorSystem.Create(...) inside Global.asax Application_Start and dispose it with system.Shutdown() on Application_End.
OWIN - create actor system in OWIN's Startup.Configuration method and shut it down by binding to host.OnAppDisposing event (how-to link).
Remember that IIS will startup your web app only after first request and tear it down automatically after some time when it's idle. Therefore make sure, that your deployment script will ping application after publishing and set idle timeout (link) for long enough if you want your Akka actor system to run continuously.
Second option
Separate your Actor System logic and deploy it, for example, as a Windows Service (or Linux deamon). Turn on Akka.Remoting for it and create a proxy client, which will forward all application long-running sensitive tasks to external service. Similar solution is often used for things such as schedulers or event buses, when your application logic must be working continuously.
In Servlet 3.0, an application's ServletContainerInitializer implementation (if any) is called when the application first BEGINS starting and any ServletContextListeners (if any) are called soon after, but still as the context is BEGINNING initialization. Likewise, if you have any Servlets with load-on-startup set, their init methods are called as the Servlets are starting up, but still BEFORE the context completes initialization.
In all of these cases, the context has not completed initialization. That is fine and I understand and agree with the reasons for that. What I'm looking for, however, is a way to be notified immediately AFTER the context has completed initialization and is open for business. As an example, it should be possible (not saying I want to do this) for this listener of sorts to perform a web request to the application it resides in. That wouldn't be possible for any of the above mentioned listeners/initializers, since they are called before the application is listening for requests.
Is it possible to do this? Doesn't have to strictly be a Servlet-spec-provided method. Could be Spring Framework or some other library that performs this task.
You can use JBoss Seam they have servlet lifecycle event #Initialized.
public void observeServletContextInitialized(#Observes #Initialized ServletContext ctx)
{
System.out.println(ctx.getServletContextName() + " initialized");
}
I have a simple app where I use global.asax to map a serviceroute to a wcf service through a custom servicehostfactory in Application_Start. The constructor of that service does some initial processing to set up the service which takes a bit of time.
I need this constructor to fire when its serviceroute is added automatically. I tried creating a clientchannel from global.asax and making a dummy call to spin up the service, but discovered the service isn't up yet -- it seems application_start has to return?
So how do I get the constructor of the service to fire when first mapped through global.asax without having to manually hit the service? Unfortunately AppFabric isn't an option for us, so I can't just use it's built-in autostart..
UPDATE
I was asked for a bit more detail;
This is like a routing management service. So I have Service1 -- it gets added as a serviceroute in global.asax. Now I have http://localhost/Service1
Inside Service1 I have a method called 'addServiceRoute'. When called, it also registers a route for Service2. Now I have http://localhost/Service1/Service2.
My initial solution from global.asax was to build a channelfactory to http://localhost/service1 but that wouldn't work. Service1 wasn't up yet and wouldn't come up till Application_Start returned (Still not sure why?). So then I thought I'd cheat and move that initial addserviceroute call to the constructor of service1. Also didn't work.
It was mentioned that this shouldnt be in the constructor -- i agree, this is just testing code.
A singleton was also mentioned, which might be ok, but I intend to have more than one instance of Service1 on a machine (in the same app pool) so I don't think that'll work?
** UPDATE #2 **
I was asked for sample code.. here it is from global.asax (trimmed a bit for brevity).. So http://localhost/Test DOES come up.. But if I have to use appfabric to warm up Test and get its constructor to fire, then don't I need Test.svc or something? How do I get appfabric to even see this service exists?
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
RouteTable.Routes.Add(
new ServiceRoute("Test", new MyServiceHostFactory(ITestService, BindingType.BasicHttpBinding, true), TestService));
}
What you describe requires singleton service (something you should avoid) because normally each call or session gets a new instance = a new call to constructor. In self hosted WCF service you can instantiate singleton service instance and pass it to ServiceHost constructor. In case of IIS hosted service used together with ServiceRoute you can try to create your own class derived from ServiceHostFactory and pass created service instance as a parameter to its constructor. In this factory class implement CreateServiceHost method and pass that existing service instance into ServiceHost constructor. To make this work your service class must still be handled as singleton through service behavior.
Btw. constructor should not do any time consuming operation. Constructor is for constructing object not for initializing infrastructure. Using constructor for such initialization is bad practice in the first place.
AppFabric autostart is what I would recommend - even though you say you cannot use it - this is the problem it was meant to solve (warming up your service).
As an alternative before AppFabric existed, you would have to use a scheduled task (a.k.a cron job) with an executable that calls into the service you want initialized. The way AppFabric autostart works is by using named pipes (net.pipe) to trigger the warm up - but it just does this exact thing when the service is recycled. The difference between the scheduled task approach and the AppFabric autostart is that the scheduled task doesn't know when your application pool has been recycled - you would need to poll your service periodically to keep it warm.
Alternatively you could consider hosting your WCF application outside of IIS via self-hosting. This would avoid the warm-up issue, but you wouldn't achieve many of the benefits of the IIS hosted container. See HttpSelfHostServer in the new MVC Web API or review using a standard ServiceHost.