Hello
I have an "OutOfMemoryException" error using .NET CORE 2.2.
The full description of the error is:
System.OutOfMemoryException:
at System.MulticastDelegate.CombineImpl (System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e)
at StackExchange.Redis.ConnectionMultiplexer.add_ConnectionRestored (StackExchange.Redis, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = c219ff1ca8c2ce46)
at V1.Sdk.Infra.Repository.RedisRepository.RegisterEvent (V1.Sdk.Infra, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null)
at V1.Sdk.Infra.Repository.RedisRepository.get_ConnectionMultiplexer (V1.Sdk.Infra, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null)
at V1.Sdk.Infra.Repository.RedisRepository.GetDatabase (V1.Sdk.Infra, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null)
at Vix.V1.Application.Services.Motorista.MotoristaService +d__17.MoveNext (Vix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = nullVix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: d: \ a \ 1 \ s \ Vix.V1.Application \ Services \ Driver \ DriverService.ObterLogado.csVix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: 31)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e)
at Vix.V1.Application.Services.Location.LocationService +d__2.MoveNext (Vix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = nullVix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: d: \ a \ 1 \ s \ Vix.V1.Application \ Services \ Location \ LocationService.UpdatePosition.csVix.V1.Application, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null: 27)
The class you use to access redis is:
public class RedisRepository
{
private static readonly object Locker = new object ();
private static IConnectionMultiplexer _connMultiplexer;
private static IConnectionMultiplexer ConnectionMultiplexer
{
get
{
if (_connMultiplexer == null ||! _connMultiplexer.IsConnected)
{
lock (Locker)
{
if (_connMultiplexer == null ||! _connMultiplexer.IsConnected)
{
_connMultiplexer = Connection;
}
}
}
RegisterEvent ();
return _connMultiplexer;
}
}
private static readonly Lazy <ConnectionMultiplexer> LazyConnection = new Lazy <ConnectionMultiplexer> (() =>
{
var connection = StackExchange.Redis.ConnectionMultiplexer.Connect (AppContextSdk.Configuration.GetConnectionString ("RedisConnection"));
return connection;
});
private static ConnectionMultiplexer Connection => LazyConnection.Value;
public static IDatabase GetDatabase ()
{
return ConnectionMultiplexer.GetDatabase (0);
}
private static void RegisterEvent ()
{
_connMultiplexer.ConnectionRestored + = ConnMultiplexer_ConnectionRestored;
_connMultiplexer.ConnectionFailed + = ConnMultiplexer_ConnectionFailed;
_connMultiplexer.ErrorMessage + = ConnMultiplexer_ErrorMessage;
_connMultiplexer.InternalError + = ConnMultiplexer_InternalError;
}
private static void ConnMultiplexer_ConnectionRestored (object sender, ConnectionFailedEventArgs and)
{
}
private static void ConnMultiplexer_ConnectionFailed (object sender, ConnectionFailedEventArgs and)
{
}
private static void ConnMultiplexer_ErrorMessage (object sender, RedisErrorEventArgs e)
{
}
private static void ConnMultiplexer_InternalError (object sender, InternalErrorEventArgs e)
{
}
}
The Redis used is Azure Redis Cache Premium 6GB.
Any idea what it might be or what you should do to solve it? Until then the solution is to restart App Service
The problem is your ConnectionMultiplexer
property. Every single time it is accessed, it adds additional event registrations. Eventually, this will explode. Before then, it is just a really bad idea. So... don't do that?
Perfect! It was exactly this point!
Thank you!
ConnectionMultiplexer is thread-safe and does not require a lock,
` public static ConnectionMultiplexer Instance
{
get
{
return conn.Value;
}
}
private static Lazy<ConnectionMultiplexer> conn = new Lazy<ConnectionMultiplexer>(
() =>
{
_instance = ConnectionMultiplexer.Connect(RedisPath);
//adds additional event registrations
_instance.ConnectionFailed += MuxerConnectionFailed;
_instance.ConnectionRestored += MuxerConnectionRestored;
_instance.ErrorMessage += MuxerErrorMessage;
_instance.HashSlotMoved += MuxerHashSlotMoved;
_instance.InternalError += MuxerInternalError;
return _instance;
}
);`
and you can try using my packaged tool to search 'Banana.Utility' in nuget.
Most helpful comment
ConnectionMultiplexer is thread-safe and does not require a lock,
` public static ConnectionMultiplexer Instance
{
get
{
return conn.Value;
}
}
and you can try using my packaged tool to search 'Banana.Utility' in nuget.