문제

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;
}
도움이 되었습니까?

해결책

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!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top