• SQLite多线程写锁文件解决方案


     

    在sqlite编程中多线程同时写时会出现异常,我写了个类来解决这个问题。

    思路很简单,就是在开始写操作时,记下写操作的托管线程id,表示目前有线程正在做写操作;其他线程来写时,需要先检测是否有进程正在做写操作,如果有就需要等待,等待到某一个配置的超时时间时,会抛出异常终止等待;如果没有则直接放行,此线程可以获得写锁。最后写操作执行完毕时需要释放锁。

    下面是具体的代码:

    SQLiteWriteLock

    /// <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
    }

    希望此文有用。

  • 相关阅读:
    27. 移除元素
    axios调用webapi报错
    MySql重装以后,修改数据库路径,打开以前的数据库报Table 'XX库.XX表' doesn't exist错误的解决办法
    SqlServer2012,设置指定数据库对指定用户开放权限
    win10无法访问服务器上的共享文件夹怎么设置,提示:你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问
    Vs2017的git的坑
    jira6.3.6创建问题不自动发邮件通知的问题
    在windows下面配置redis集群遇到的一些坑
    SqlServer2008 无法修改表,超时时间已到 在操作完成之前超时解决方法
    小程序中也可以使用三元运算符且可嵌套使用
  • 原文地址:https://www.cnblogs.com/sczw-maqing/p/3368536.html
Copyright © 2020-2023  润新知