Index: System.Data.SQLite/SQLiteConnection.cs
==================================================================
--- System.Data.SQLite/SQLiteConnection.cs
+++ System.Data.SQLite/SQLiteConnection.cs
@@ -194,11 +194,18 @@
/// N
/// Y
///
/// -
/// Pooling
- /// True - Use connection pooling
False - Do not use connection pooling
+ ///
+ /// True - Use connection pooling.
+ /// False - Do not use connection pooling.
+ /// WARNING: Setting this property to True should be avoided by
+ /// applications that make use of WPF (either directly or indirectly) due
+ /// to possible deadlocks that can occur during the finalization of some
+ /// WPF objects.
+ ///
/// N
/// False
///
/// -
/// FailIfMissing
@@ -1165,11 +1172,18 @@
/// N
/// Y
///
/// -
/// Pooling
- /// True - Use connection pooling
False - Do not use connection pooling
+ ///
+ /// True - Use connection pooling.
+ /// False - Do not use connection pooling.
+ /// WARNING: Setting this property to True should be avoided by
+ /// applications that make use of WPF (either directly or indirectly) due
+ /// to possible deadlocks that can occur during the finalization of some
+ /// WPF objects.
+ ///
/// N
/// False
///
/// -
/// FailIfMissing
Index: System.Data.SQLite/SQLiteConnectionPool.cs
==================================================================
--- System.Data.SQLite/SQLiteConnectionPool.cs
+++ System.Data.SQLite/SQLiteConnectionPool.cs
@@ -1,45 +1,50 @@
-/********************************************************
- * ADO.NET 2.0 Data Provider for SQLite Version 3.X
- * Written by Robert Simpson (robert@blackcastlesoft.com)
- *
- * Released to the public domain, use at your own risk!
- ********************************************************/
-
-namespace System.Data.SQLite
-{
- using System;
+/********************************************************
+ * ADO.NET 2.0 Data Provider for SQLite Version 3.X
+ * Written by Robert Simpson (robert@blackcastlesoft.com)
+ *
+ * Released to the public domain, use at your own risk!
+ ********************************************************/
+
+namespace System.Data.SQLite
+{
+ using System;
using System.Collections.Generic;
- using System.Threading;
-
- internal static class SQLiteConnectionPool
- {
- ///
- /// Keeps track of connections made on a specified file. The PoolVersion dictates whether old objects get
- /// returned to the pool or discarded when no longer in use.
- ///
- internal class Pool
- {
- internal readonly Queue Queue = new Queue();
- internal int PoolVersion;
- internal int MaxPoolSize;
-
- internal Pool(int version, int maxSize)
- {
- PoolVersion = version;
- MaxPoolSize = maxSize;
- }
- }
-
- ///
- /// The connection pool object
- ///
- private static SortedList _connections = new SortedList(StringComparer.OrdinalIgnoreCase);
-
- ///
- /// The default version number new pools will get
- ///
+ using System.Threading;
+
+ ///
+ /// This class should not be used by applications that make use of WPF
+ /// (either directly or indirectly) due to possible deadlocks that can occur
+ /// during finalization of some WPF objects.
+ ///
+ internal static class SQLiteConnectionPool
+ {
+ ///
+ /// Keeps track of connections made on a specified file. The PoolVersion dictates whether old objects get
+ /// returned to the pool or discarded when no longer in use.
+ ///
+ internal class Pool
+ {
+ internal readonly Queue Queue = new Queue();
+ internal int PoolVersion;
+ internal int MaxPoolSize;
+
+ internal Pool(int version, int maxSize)
+ {
+ PoolVersion = version;
+ MaxPoolSize = maxSize;
+ }
+ }
+
+ ///
+ /// The connection pool object
+ ///
+ private static SortedList _connections = new SortedList(StringComparer.OrdinalIgnoreCase);
+
+ ///
+ /// The default version number new pools will get
+ ///
private static int _poolVersion = 1;
///
/// The number of connections successfully opened from any pool.
/// This value is incremented by the Remove method.
@@ -48,73 +53,73 @@
///
/// The number of connections successfully closed from any pool.
/// This value is incremented by the Add method.
///
- private static int _poolClosed = 0;
-
- ///
- /// Counts the number of pool entries matching the specified file name.
- ///
- /// The file name to match or null to match all files.
+ private static int _poolClosed = 0;
+
+ ///
+ /// Counts the number of pool entries matching the specified file name.
+ ///
+ /// The file name to match or null to match all files.
/// The pool entry counts for each matching file.
/// The total number of connections successfully opened from any pool.
- /// The total number of connections successfully closed from any pool.
- /// The total number of pool entries for all matching files.
- internal static void GetCounts(
- string fileName,
- ref Dictionary counts,
- ref int openCount,
- ref int closeCount,
- ref int totalCount
- )
- {
- lock (_connections)
+ /// The total number of connections successfully closed from any pool.
+ /// The total number of pool entries for all matching files.
+ internal static void GetCounts(
+ string fileName,
+ ref Dictionary counts,
+ ref int openCount,
+ ref int closeCount,
+ ref int totalCount
+ )
+ {
+ lock (_connections)
{
openCount = _poolOpened;
- closeCount = _poolClosed;
-
- if (counts == null)
- {
- counts = new Dictionary(
- StringComparer.OrdinalIgnoreCase);
- }
-
- if (fileName != null)
- {
- Pool queue;
-
- if (_connections.TryGetValue(fileName, out queue))
- {
- Queue poolQueue = queue.Queue;
- int count = (poolQueue != null) ? poolQueue.Count : 0;
-
- counts.Add(fileName, count);
- totalCount += count;
- }
- }
- else
- {
- foreach (KeyValuePair pair in _connections)
- {
- if (pair.Value == null)
- continue;
-
- Queue poolQueue = pair.Value.Queue;
- int count = (poolQueue != null) ? poolQueue.Count : 0;
-
- counts.Add(pair.Key, count);
- totalCount += count;
- }
- }
- }
- }
-
- ///
- /// Attempt to pull a pooled connection out of the queue for active duty
- ///
- /// The filename for a desired connection
+ closeCount = _poolClosed;
+
+ if (counts == null)
+ {
+ counts = new Dictionary(
+ StringComparer.OrdinalIgnoreCase);
+ }
+
+ if (fileName != null)
+ {
+ Pool queue;
+
+ if (_connections.TryGetValue(fileName, out queue))
+ {
+ Queue poolQueue = queue.Queue;
+ int count = (poolQueue != null) ? poolQueue.Count : 0;
+
+ counts.Add(fileName, count);
+ totalCount += count;
+ }
+ }
+ else
+ {
+ foreach (KeyValuePair pair in _connections)
+ {
+ if (pair.Value == null)
+ continue;
+
+ Queue poolQueue = pair.Value.Queue;
+ int count = (poolQueue != null) ? poolQueue.Count : 0;
+
+ counts.Add(pair.Key, count);
+ totalCount += count;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Attempt to pull a pooled connection out of the queue for active duty
+ ///
+ /// The filename for a desired connection
/// The maximum size the connection pool for the filename can be
/// The pool version the returned connection will belong to
/// Returns NULL if no connections were available. Even if none are, the poolversion will still be a valid pool version
internal static SQLiteConnectionHandle Remove(string fileName, int maxPoolSize, out int version)
{
@@ -270,141 +275,141 @@
_connections.Add(fileName, queue);
}
}
return null;
- }
-
- ///
- /// Clears out all pooled connections and rev's up the default pool version to force all old active objects
- /// not in the pool to get discarded rather than returned to their pools.
- ///
- internal static void ClearAllPools()
- {
- lock (_connections)
- {
- foreach (KeyValuePair pair in _connections)
+ }
+
+ ///
+ /// Clears out all pooled connections and rev's up the default pool version to force all old active objects
+ /// not in the pool to get discarded rather than returned to their pools.
+ ///
+ internal static void ClearAllPools()
+ {
+ lock (_connections)
+ {
+ foreach (KeyValuePair pair in _connections)
{
if (pair.Value == null)
continue;
Queue poolQueue = pair.Value.Queue;
- while (poolQueue.Count > 0)
+ while (poolQueue.Count > 0)
{
WeakReference cnn = poolQueue.Dequeue();
- if (cnn == null) continue;
- SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
- if (hdl != null)
- {
- hdl.Dispose();
- }
- GC.KeepAlive(hdl);
- }
-
- // Keep track of the highest revision so we can go one higher when we're finished
- if (_poolVersion <= pair.Value.PoolVersion)
- _poolVersion = pair.Value.PoolVersion + 1;
- }
- // All pools are cleared and we have a new highest version number to force all old version active items to get discarded
- // instead of going back to the queue when they are closed.
- // We can get away with this because we've pumped up the _poolVersion out of range of all active connections, so they
- // will all get discarded when they try to put themselves back in their pool.
- _connections.Clear();
- }
- }
-
- ///
- /// Clear a given pool for a given filename. Discards anything in the pool for the given file, and revs the pool
- /// version so current active objects on the old version of the pool will get discarded rather than be returned to the pool.
- ///
- /// The filename of the pool to clear
- internal static void ClearPool(string fileName)
- {
- lock (_connections)
- {
- Pool queue;
- if (_connections.TryGetValue(fileName, out queue) == true)
- {
+ if (cnn == null) continue;
+ SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
+ if (hdl != null)
+ {
+ hdl.Dispose();
+ }
+ GC.KeepAlive(hdl);
+ }
+
+ // Keep track of the highest revision so we can go one higher when we're finished
+ if (_poolVersion <= pair.Value.PoolVersion)
+ _poolVersion = pair.Value.PoolVersion + 1;
+ }
+ // All pools are cleared and we have a new highest version number to force all old version active items to get discarded
+ // instead of going back to the queue when they are closed.
+ // We can get away with this because we've pumped up the _poolVersion out of range of all active connections, so they
+ // will all get discarded when they try to put themselves back in their pool.
+ _connections.Clear();
+ }
+ }
+
+ ///
+ /// Clear a given pool for a given filename. Discards anything in the pool for the given file, and revs the pool
+ /// version so current active objects on the old version of the pool will get discarded rather than be returned to the pool.
+ ///
+ /// The filename of the pool to clear
+ internal static void ClearPool(string fileName)
+ {
+ lock (_connections)
+ {
+ Pool queue;
+ if (_connections.TryGetValue(fileName, out queue) == true)
+ {
queue.PoolVersion++;
Queue poolQueue = queue.Queue;
if (poolQueue == null) return;
- while (poolQueue.Count > 0)
+ while (poolQueue.Count > 0)
{
WeakReference cnn = poolQueue.Dequeue();
- if (cnn == null) continue;
- SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
- if (hdl != null)
- {
- hdl.Dispose();
- }
- GC.KeepAlive(hdl);
- }
- }
- }
- }
-
- ///
- /// Return a connection to the pool for someone else to use.
- ///
- /// The filename of the pool to use
- /// The connection handle to pool
- /// The pool version the handle was created under
- ///
- /// If the version numbers don't match between the connection and the pool, then the handle is discarded.
- ///
- internal static void Add(string fileName, SQLiteConnectionHandle hdl, int version)
- {
- lock (_connections)
- {
- // If the queue doesn't exist in the pool, then it must've been cleared sometime after the connection was created.
- Pool queue;
- if (_connections.TryGetValue(fileName, out queue) == true && version == queue.PoolVersion)
- {
+ if (cnn == null) continue;
+ SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
+ if (hdl != null)
+ {
+ hdl.Dispose();
+ }
+ GC.KeepAlive(hdl);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Return a connection to the pool for someone else to use.
+ ///
+ /// The filename of the pool to use
+ /// The connection handle to pool
+ /// The pool version the handle was created under
+ ///
+ /// If the version numbers don't match between the connection and the pool, then the handle is discarded.
+ ///
+ internal static void Add(string fileName, SQLiteConnectionHandle hdl, int version)
+ {
+ lock (_connections)
+ {
+ // If the queue doesn't exist in the pool, then it must've been cleared sometime after the connection was created.
+ Pool queue;
+ if (_connections.TryGetValue(fileName, out queue) == true && version == queue.PoolVersion)
+ {
ResizePool(queue, true);
Queue poolQueue = queue.Queue;
if (poolQueue == null) return;
poolQueue.Enqueue(new WeakReference(hdl, false));
- Interlocked.Increment(ref _poolClosed);
- }
- else
- {
- hdl.Close();
- }
- GC.KeepAlive(hdl);
- }
- }
-
- ///
- /// We don't have to thread-lock anything in this function, because it's only called by other functions above
- /// which already have a thread-safe lock.
- ///
- /// The queue to resize
- /// If a function intends to add to the pool, this is true, which forces the resize
- /// to take one more than it needs from the pool
- private static void ResizePool(Pool queue, bool forAdding)
- {
- int target = queue.MaxPoolSize;
-
+ Interlocked.Increment(ref _poolClosed);
+ }
+ else
+ {
+ hdl.Close();
+ }
+ GC.KeepAlive(hdl);
+ }
+ }
+
+ ///
+ /// We don't have to thread-lock anything in this function, because it's only called by other functions above
+ /// which already have a thread-safe lock.
+ ///
+ /// The queue to resize
+ /// If a function intends to add to the pool, this is true, which forces the resize
+ /// to take one more than it needs from the pool
+ private static void ResizePool(Pool queue, bool forAdding)
+ {
+ int target = queue.MaxPoolSize;
+
if (forAdding && target > 0) target--;
Queue poolQueue = queue.Queue;
if (poolQueue == null) return;
- while (poolQueue.Count > target)
+ while (poolQueue.Count > target)
{
WeakReference cnn = poolQueue.Dequeue();
- if (cnn == null) continue;
- SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
- if (hdl != null)
- {
- hdl.Dispose();
- }
- GC.KeepAlive(hdl);
- }
- }
- }
-}
+ if (cnn == null) continue;
+ SQLiteConnectionHandle hdl = cnn.Target as SQLiteConnectionHandle;
+ if (hdl != null)
+ {
+ hdl.Dispose();
+ }
+ GC.KeepAlive(hdl);
+ }
+ }
+ }
+}