Question

I have a singleton database class which may be accessed from hundreds of threads simultaneously. Each thread gets its own connection. Since I cannot control the number of threads, I need to limit the number of concurrent connections. I decided to use a semaphore as shown below. Now, the connection is always assigned in a using block so it is indeed guaranteed to get closed - even if an exception is thrown.

However, it seems that StateChange is not called when an exception is thrown. Obviously, this breaks my code below.

QUESTION: How do I make sure StateChange is indeed called in this scenario? Or, if not possible, how do I solve this particular problem?

private const int MAX_CONNECTIONS = 10;
private static SemaphoreSlim connectionLock = new SemaphoreSlim(MAX_CONNECTIONS);

protected DbConnection OpenConnection()
{
    var connection = ProviderFactory.CreateConnection();
    connection.ConnectionString = ConnectionString;
    connection.Open();

    connectionLock.Wait();

    connection.StateChange += (s, e) =>
    {
        if (e.CurrentState == ConnectionState.Closed)
        {
            connectionLock.Release();
        }
    };

    return connection;
}
Was it helpful?

Solution

Ok... It seems the event is indeed called IF the exception is produced after the call to OpenConnection. When I tested this, I put an explicit throw new Exception() just before returning the connection... oops!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top