diff --git a/src/Umbraco.Core/CoreBootManager.cs b/src/Umbraco.Core/CoreBootManager.cs
index 00e0daebc8..03a5206522 100644
--- a/src/Umbraco.Core/CoreBootManager.cs
+++ b/src/Umbraco.Core/CoreBootManager.cs
@@ -241,6 +241,8 @@ namespace Umbraco.Core
// we're ready to serve content!
ApplicationContext.IsReady = true;
+ //And now we can dispose of our startup handlers - save some memory
+ ApplicationEventsResolver.Current.Dispose();
//stop the timer and log the output
_timer.Dispose();
diff --git a/src/Umbraco.Core/ObjectResolution/ApplicationEventsResolver.cs b/src/Umbraco.Core/ObjectResolution/ApplicationEventsResolver.cs
index 875fcd051f..3d1d44133b 100644
--- a/src/Umbraco.Core/ObjectResolution/ApplicationEventsResolver.cs
+++ b/src/Umbraco.Core/ObjectResolution/ApplicationEventsResolver.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
using umbraco.interfaces;
namespace Umbraco.Core.ObjectResolution
@@ -8,7 +9,10 @@ namespace Umbraco.Core.ObjectResolution
///
/// A resolver to return all IApplicationEvents objects
///
- internal sealed class ApplicationEventsResolver : ManyObjectsResolverBase
+ ///
+ /// This is disposable because after the app has started it should be disposed to release any memory being occupied by instances.
+ ///
+ internal sealed class ApplicationEventsResolver : ManyObjectsResolverBase, IDisposable
{
private readonly LegacyStartupHandlerResolver _legacyResolver;
@@ -53,7 +57,7 @@ namespace Umbraco.Core.ObjectResolution
protected override bool SupportsClear
{
- get { return false; }
+ get { return false; }
}
protected override bool SupportsInsert
@@ -61,7 +65,7 @@ namespace Umbraco.Core.ObjectResolution
get { return false; }
}
- private class LegacyStartupHandlerResolver : ManyObjectsResolverBase
+ private class LegacyStartupHandlerResolver : ManyObjectsResolverBase, IDisposable
{
internal LegacyStartupHandlerResolver(IEnumerable legacyStartupHandlers)
: base(legacyStartupHandlers)
@@ -73,7 +77,72 @@ namespace Umbraco.Core.ObjectResolution
{
get { return Values; }
}
- }
+ public void Dispose()
+ {
+ Reset();
+ }
+ }
+
+ private bool _disposed;
+ private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim();
+
+ ///
+ /// Gets a value indicating whether this instance is disposed.
+ ///
+ ///
+ /// true if this instance is disposed; otherwise, false.
+ ///
+ public bool IsDisposed
+ {
+ get { return _disposed; }
+ }
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ /// 2
+ public void Dispose()
+ {
+ Dispose(true);
+
+ // Use SupressFinalize in case a subclass of this type implements a finalizer.
+ GC.SuppressFinalize(this);
+ }
+
+ ~ApplicationEventsResolver()
+ {
+ // Run dispose but let the class know it was due to the finalizer running.
+ Dispose(false);
+ }
+
+ private void Dispose(bool disposing)
+ {
+ // Only operate if we haven't already disposed
+ if (IsDisposed || disposing == false) return;
+
+ using (new WriteLock(_disposalLocker))
+ {
+ // Check again now we're inside the lock
+ if (IsDisposed) return;
+
+ // Call to actually release resources. This method is only
+ // kept separate so that the entire disposal logic can be used as a VS snippet
+ DisposeResources();
+
+ // Indicate that the instance has been disposed.
+ _disposed = true;
+ }
+ }
+
+ ///
+ /// Clear out all of the instances, we don't want them hanging around and cluttering up memory
+ ///
+ private void DisposeResources()
+ {
+ _legacyResolver.Dispose();
+ Reset();
+ }
+
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs
index 0edaf68243..c19ba000a0 100644
--- a/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs
+++ b/src/Umbraco.Core/ObjectResolution/ManyObjectsResolverBase.cs
@@ -322,7 +322,7 @@ namespace Umbraco.Core.ObjectResolution
}
///
- /// Clears the list of types.
+ /// Clears the list of types
///
/// the resolver does not support clearing types.
public virtual void Clear()
@@ -336,6 +336,20 @@ namespace Umbraco.Core.ObjectResolution
}
}
+ ///
+ /// WARNING! Do not use this unless you know what you are doing, clear all types registered and instances
+ /// created. Typically only used if a resolver is no longer used in an application and memory is to be GC'd
+ ///
+ internal void Reset()
+ {
+ using (new WriteLock(_lock))
+ {
+ _instanceTypes.Clear();
+ _sortedValues = null;
+ _applicationInstances = null;
+ }
+ }
+
///
/// Inserts a type at the specified index.
///
diff --git a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs
index e4d2496903..c4d3c1c572 100644
--- a/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs
+++ b/src/Umbraco.Core/Persistence/Migrations/Upgrades/TargetVersionSixTwoZero/AdditionalIndexesAndKeys.cs
@@ -8,10 +8,10 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
public override void Up()
{
- Create.Index("IX_umbracoNodeTrashed").OnTable("umbracoNode").OnColumn("trashed").Ascending().WithOptions().NonClustered();
- Create.Index("IX_cmsContentVersion_ContentId").OnTable("cmsContentVersion").OnColumn("ContentId").Ascending().WithOptions().NonClustered();
- Create.Index("IX_cmsDocument_published").OnTable("cmsDocument").OnColumn("published").Ascending().WithOptions().NonClustered();
- Create.Index("IX_cmsDocument_newest").OnTable("cmsDocument").OnColumn("newest").Ascending().WithOptions().NonClustered();
+ //Create.Index("IX_umbracoNodeTrashed").OnTable("umbracoNode").OnColumn("trashed").Ascending().WithOptions().NonClustered();
+ //Create.Index("IX_cmsContentVersion_ContentId").OnTable("cmsContentVersion").OnColumn("ContentId").Ascending().WithOptions().NonClustered();
+ //Create.Index("IX_cmsDocument_published").OnTable("cmsDocument").OnColumn("published").Ascending().WithOptions().NonClustered();
+ //Create.Index("IX_cmsDocument_newest").OnTable("cmsDocument").OnColumn("newest").Ascending().WithOptions().NonClustered();
}
public override void Down()