在sqlite编程中多线程同时写时会出现异常,我写了个类来解决这个问题。
思路很简单,就是在开始写操作时,记下写操作的托管线程id,表示目前有线程正在做写操作;其他线程来写时,需要先检测是否有进程正在做写操作,如果有就需要等待,等待到某一个配置的超时时间时,会抛出异常终止等待;如果没有则直接放行,此线程可以获得写锁。最后写操作执行完毕时需要释放锁。
下面是具体的代码:
- ///<summary>
- ///用于在多线程访问sqlite时防止同步写导致锁文件
- ///
- ///使用方法:
- ///using(sqliteWriteLocksqliteLock=newsqliteWriteLock(sqlite链接字符串))
- ///{
- /////sqlite写操作代码
- ///}
- ///
- ///可以通过在配置文件appSettings节中添加设置sqliteWriteLockTimeout的value值控制锁等待的超时时间,该值必须为正整数数字,单位为毫秒,
- ///默认的超时时间是1000ms
- ///</summary>
- publicsealedclasssqliteWriteLock:IDisposable
- {
- #region静态字段和属性
- constshortWAIT_TIME=5;
- staticreadonlyobjectlocker=newobject();
- staticDictionary<string,int>_dbThreadIdDict=newDictionary<string,int>();
- ///<summary>
- ///获得写操作的超时时间,单位为毫秒,可以通过配置文件appSettings节中添加设置sqliteWriteLockTimeout的value值控制锁等待的超时时间,该值必须为正整数数字,单位为毫秒
- ///默认的超时时间是1000ms
- ///</summary>
- publicstaticintsqliteWriteLockTimeout
- {
- get
- {
- stringconfigValule=ConfigurationManager.AppSettings["sqliteWriteLockTimeout"];
- if(!string.IsNullOrEmpty(configValule))
- {
- returnint.Parse(configValule);
- }
- return1000;
- }
- }
- #endregion
- privatereadonlystring_connString;
- //隐藏无参构造函数
- privatesqliteWriteLock(){}
- publicsqliteWriteLock(stringconnString)
- {
- _connString=connString;
- AcquireWriteLock();
- }
- #region私有方法
- privatevoidAcquireWriteLock()
- {
- intthreadId=Thread.CurrentThread.ManagedThreadId;
- intwaitTimes=0;
- while(_dbThreadIdDict.ContainsKey(_connString)&&_dbThreadIdDict[_connString]!=threadId)
- {
- Thread.Sleep(WAIT_TIME);
- waitTimes+=WAIT_TIME;
- #ifDEBUG
- Console.WriteLine(_connString+"waitfor"+waitTimes+"ms");
- #endif
- if(waitTimes>sqliteWriteLockTimeout)
- {
- thrownewTimeoutException("sqlite等待写操作超时");
- }
- }
- lock(locker)
- {
- if(!_dbThreadIdDict.ContainsKey(_connString))
- _dbThreadIdDict.Add(_connString,threadId);
- }
- }
- privatevoidReleaseWriteLock()
- {
- lock(locker)
- {
- if(_dbThreadIdDict.ContainsKey(_connString))
- {
- _dbThreadIdDict.Remove(_connString);
- }
- }
- }
- #endregion
- #regionIDisposable成员
- publicvoidDispose()
- {
- ReleaseWriteLock();
- }
- #endregion
- }
希望此文有用。