SQLite多線程寫鎖文件解決方案

 

在sqlite編程中多線程同時寫時會出現異常,我寫了個類來解決這個問題。sql

思路很簡單,就是在開始寫操做時,記下寫操做的託管線程id,表示目前有線程正在作寫操做;其餘線程來寫時,須要先檢測是否有進程正在作寫操做,若是有就須要等待,等待到某一個配置的超時時間時,會拋出異常終止等待;若是沒有則直接放行,此線程能夠得到寫鎖。最後寫操做執行完畢時須要釋放鎖。編程

下面是具體的代碼:多線程

SQLiteWriteLock app

/// <summary>
/// 用於在多線程訪問sqlite時防止同步寫致使鎖文件
///
/// 使用方法:
/// using (SQLiteWriteLock sqliteLock = new SQLiteWriteLock(SQLite連接字符串))
/// {
///     //sqlite 寫操做代碼
/// }
///
/// 能夠經過在配置文件appSettings節中添加設置 SQLiteWriteLockTimeout 的value值控制鎖等待的超時時間,該值必須爲正整數數字,單位爲毫秒,
/// 默認的超時時間是1000ms
/// </summary>
public sealed class SQLiteWriteLock : IDisposable
{
#region 靜態字段和屬性
const short WAIT_TIME = 5;
static readonly object locker = new object();
static Dictionary<string, int> _dbThreadIdDict = new Dictionary<string, int>();
/// <summary>
/// 得到寫操做的超時時間,單位爲毫秒,能夠經過配置文件appSettings節中添加設置 SQLiteWriteLockTimeout 的value值控制鎖等待的超時時間,該值必須爲正整數數字,單位爲毫秒
/// 默認的超時時間是1000ms
/// </summary>
public static int SQLiteWriteLockTimeout
    {
get
        {
string configValule = ConfigurationManager.AppSettings["SQLiteWriteLockTimeout"];
if (!string.IsNullOrEmpty(configValule))
            {
return int.Parse(configValule);
            }
return 1000;
        }
    }
#endregion
private readonly string _connString;
//隱藏無參構造函數
private SQLiteWriteLock() { }
public SQLiteWriteLock(string connString)
    {
        _connString = connString;
        AcquireWriteLock();
    }
#region 私有方法
private void AcquireWriteLock()
    {
int threadId = Thread.CurrentThread.ManagedThreadId;
int waitTimes = 0;
while (_dbThreadIdDict.ContainsKey(_connString) && _dbThreadIdDict[_connString] != threadId)
        {
            Thread.Sleep(WAIT_TIME);
            waitTimes += WAIT_TIME;
#if DEBUG
            Console.WriteLine(_connString + " wait for " + waitTimes + " ms");
#endif
if (waitTimes > SQLiteWriteLockTimeout)
            {
throw new TimeoutException("SQLite等待寫操做超時");
            }
        }
lock (locker)
        {
if (!_dbThreadIdDict.ContainsKey(_connString))
                _dbThreadIdDict.Add(_connString, threadId);
        }
    }
private void ReleaseWriteLock()
    {
lock (locker)
        {
if (_dbThreadIdDict.ContainsKey(_connString))
            {
                _dbThreadIdDict.Remove(_connString);
            }
        }
    }
#endregion
#region IDisposable 成員
public void Dispose()
    {
        ReleaseWriteLock();
    }
#endregion
}

但願此文有用。函數

相關文章
相關標籤/搜索