在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

}

希望此文有用。

SQLite多线程写锁文件解决方案的更多相关文章

  1. SQLite数据库在多线程写锁文件的解决办法

    参考了很多SQLITE数据库多线程的解决办法 我自己写了一个SQLITEHELPER 来解决这个问题 希望大家多多指教 调用的时候  SQLLiteDBHelper _SQLLiteDBHelper ...

  2. (原创)android Sqlite多线程访问异常解决方案

    在开发Android的程序的时候sqlite数据库是经常用到的:在多线程访问数据库的时候会出现这样的异常:java.lang.IllegalStateException: Cannot perform ...

  3. Sqlite多线程相关整理

    Sqlite多线程相关整理 Sqlite With MultiThreads 什么是线程安全? 当多个线程访问某个方法时,不管你通过怎样的调用方式.或者说这些线程如何交替地执行,我们在主程序中不需要去 ...

  4. JAVA多线程读写文件范例

    在写之前先声明,本文是基于之前在博客园网站上检索到的一份JAVA多线程读写文件的示例,我在写自己的程序时是在那位作者写的基础上做了改良,但已不记得原文的地址.如果有知情者,烦请帖出地址,我在此文上加入 ...

  5. SQLite多线程下的并发操作

    标签: sqlite多线程数据库跨平台嵌入式class 2011-04-14 13:29 26939人阅读 评论(2) 收藏 举报 这两天一直在捣鼓SQLite数据库,基本的操作就不说了,比较简单,打 ...

  6. Atitit.android播放smb 网络邻居视频文件解决方案

    Atitit.android播放smb 网络邻居视频文件解决方案 Android4.4 1.1. Android4视频播放器不能直接地支持smb协议..子好先转换成个http流 1.2. ES文件浏览 ...

  7. CoreData和SQLite多线程访问时的线程安全

    关于CoreData和SQLite多线程访问时的线程安全问题 数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常 ...

  8. ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案

    摘要: ueditor1.3.6jsp版在struts2应用中上传图片报"未找到上传文件"解决方案 在struts2应用中使用ueditor富文本编辑器上传图片或者附件时,即使配置 ...

  9. AccessRandomFile多线程下载文件

    写一个工具类 package com.pb.thread.demo; import java.io.File; import java.io.FileNotFoundException; import ...

随机推荐

  1. 【ASP.NET MVC】"[A]System.Web.WebPages.Razor.Configuration.HostSection 无法强制转换为 ..."的解决办法

    1.错误页面: “/”应用程序中的服务器错误. [A]System.Web.WebPages.Razor.Configuration.HostSection 无法强制转换为 [B]System.Web ...

  2. iOS开发实践:一个类微博客户端从启动到与用户交互的过程

    本文基于数据字典和数据流图两种工具讲述一个完整微博客户端的实现.数据字典和数据流图都可以用来表达线程的执行流程,同时定义了需要的类,是进一步设计类的基础. 数据字典实际上是一张表,表的第一个字段是程序 ...

  3. 函数与关系实例,函数运算与SQL,试验与关系元组

    函数是一个集合,它的每个元素都是二元组或多元组.例如 f = { (x, y) | x∈R & y∈R & y = 2x } ,g = { (x, y, z) | (x, y, z)∈ ...

  4. wifi详解(二)

    1        Wifi模块解析和启动流程 1.1      框架分析 WIFI整体框架如图所示: 首先,用户程序使用WifiManager类来管理Wifi模块,它能够获得Wifi模块的状态,配置和 ...

  5. Oracle存储过程实现返回多个结果集 在构造函数方法中使用 dataset

    原文 Oracle存储过程实现返回多个结果集 在构造函数方法中使用 dataset DataSet相当你用的数据库: DataTable相当于你的表.一个 DataSet 可以包含多个 DataTab ...

  6. bjfu1238 卡特兰数取余

    题目就是指定n,求卡特兰数Ca(n)%m.求卡特兰数有递推公式.通项公式和近似公式三种,因为要取余,所以近似公式直接无法使用,递推公式我简单试了一下,TLE.所以只能从通项公式入手. Ca(n) = ...

  7. 扩展Fitnesse的ScriptTable:支持if-then

    Fitnesse的ScriptTable只能顺序执行所有行,本博文介绍如何让ScriptTable支持if-then,来条件执行一行. 首先普及一下概念,什么是Fitnesse,听一听.NET版Cuc ...

  8. 修改Zabbix默认运行账户

    默认Zabbix运行的账户是Zabbix,但在自动部署的时候,Agent与Server的先后顺序不定,而且官方不建议两者使用同一个账户.   所以,解压压缩包后,进入目录: vi configure ...

  9. SVM:从理论到OpenCV实践

    (转载请注明出处:http://blog.csdn.net/zhazhiqiang/ 未经允许请勿用于商业用途)   一.理论 参考网友的博客: (1)[理论]支持向量机1: Maximum Marg ...

  10. MFC学习20160718(GetModuleFileName&&GetAppDataPath)

    1.标题栏设置 一.对话框标题栏内容为静态 直接在对话框属性“General”的“Caption”中修改. 二.对话框标题栏内容为动态生成的 在对应对话框的初始化函数OnInitDialog()中添加 ...