Quantcast
Channel: MySQL Forums - Connector/NET and C#, Mono, .Net
Viewing all articles
Browse latest Browse all 1447

An Exception at MySqlPoolManager.GetPoolAsync (no replies)

$
0
0
When i use this package,it occasionally threw the following exception during startup:


An item with the same key has already been added. Key: database=;server=;user id=;password=;characterset=;pooling=True;allowzerodatetime=True at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at MySql.Data.MySqlClient.MySqlPoolManager.GetPoolAsync(MySqlConnectionStringBuilder settings, Boolean execAsync, CancellationToken cancellationToken) at MySql.Data.MySqlClient.MySqlConnection.OpenAsync(Boolean execAsync, CancellationToken cancellationToken) at MySql.Data.MySqlClient.MySqlConnection.Open() at


I think this exception is caused by multi-threading,and you can reporduce it with the following code:

```C#
var connStr = "Initial Catalog=***;Data Source='***';User Id='***';Password='***';charset='utf8mb4';pooling=true;Allow Zero Datetime=True;";
Parallel.For(0, 10, (i) =>
{
try
{
using (var conn = new MySqlConnection(connStr))
{
conn.Open();

}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
});
```

After reading the source code,I believe that this bug is casused by MySqlPoolManager incorrectly using SemaphoreSlim:

```C#
public static async Task<MySqlPool> GetPoolAsync(MySqlConnectionStringBuilder settings, bool execAsync, CancellationToken cancellationToken)
{
string text = GetKey(settings);
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1);
semaphoreSlim.Wait(CancellationToken.None);
Pools.TryGetValue(text, out var value);
if (value == null)
{
value = await MySqlPool.CreateMySqlPoolAsync(settings, execAsync, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
Pools.Add(text, value);
}
else
{
value.Settings = settings;
}

semaphoreSlim.Release();
return value;
}
```

I think the correct way to do it shoule be like this:
```
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1);
public static async Task<MySqlPool> GetPoolAsync(MySqlConnectionStringBuilder settings, bool execAsync, CancellationToken cancellationToken)
{
string text = GetKey(settings);

semaphoreSlim.Wait(CancellationToken.None);
Pools.TryGetValue(text, out var value);
if (value == null)
{
value = await MySqlPool.CreateMySqlPoolAsync(settings, execAsync, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
Pools.Add(text, value);
}
else
{
value.Settings = settings;
}

semaphoreSlim.Release();
return value;
}
```

Viewing all articles
Browse latest Browse all 1447

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>