C#解決SQlite并發(fā)異常問題的方法(使用讀寫鎖)
本文實例講述了C#解決SQlite并發(fā)異常問題的方法。分享給大家供大家參考,具體如下:
使用C#訪問sqlite時,常會遇到多線程并發(fā)導致SQLITE數(shù)據(jù)庫損壞的問題。
SQLite是文件級別的數(shù)據(jù)庫,其鎖也是文件級別的:多個線程可以同時讀,但是同時只能有一個線程寫。Android提供了SqliteOpenHelper類,加入Java的鎖機制以便調用。但在C#中未提供類似功能。
作者利用讀寫鎖(ReaderWriterLock),達到了多線程安全訪問的目標。
using System; using System.Collections.Generic; using System.Text; using System.Data.SQLite; using System.Threading; using System.Data; namespace DataAccess { ///////////////// public sealed class SqliteConn { private bool m_disposed; private static Dictionary<String, SQLiteConnection> connPool = new Dictionary<string, SQLiteConnection>(); private static Dictionary<String, ReaderWriterLock> rwl = new Dictionary<String, ReaderWriterLock>(); private static readonly SqliteConn instance = new SqliteConn(); private static string DEFAULT_NAME = "LOCAL"; #region Init // 使用單例,解決初始化與銷毀時的問題 private SqliteConn() { rwl.Add("LOCAL", new ReaderWriterLock()); rwl.Add("DB1", new ReaderWriterLock()); connPool.Add("LOCAL", CreateConn("\\local.db")); connPool.Add("DB1", CreateConn("\\db1.db")); Console.WriteLine("INIT FINISHED"); } private static SQLiteConnection CreateConn(string dbName) { SQLiteConnection _conn = new SQLiteConnection(); try { string pstr = "pwd"; SQLiteConnectionStringBuilder connstr = new SQLiteConnectionStringBuilder(); connstr.DataSource = Environment.CurrentDirectory + dbName; _conn.ConnectionString = connstr.ToString(); _conn.SetPassword(pstr); _conn.Open(); return _conn; } catch (Exception exp) { Console.WriteLine("===CONN CREATE ERR====\r\n{0}", exp.ToString()); return null; } } #endregion #region Destory // 手動控制銷毀,保證數(shù)據(jù)完整性 public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected void Dispose(bool disposing) { if (!m_disposed) { if (disposing) { // Release managed resources Console.WriteLine("關閉本地DB連接..."); CloseConn(); } // Release unmanaged resources m_disposed = true; } } ~SqliteConn() { Dispose(false); } public void CloseConn() { foreach (KeyValuePair<string, SQLiteConnection> item in connPool) { SQLiteConnection _conn = item.Value; String _connName = item.Key; if (_conn != null && _conn.State != ConnectionState.Closed) { try { _conn.Close(); _conn.Dispose(); _conn = null; Console.WriteLine("Connection {0} Closed.", _connName); } catch (Exception exp) { Console.WriteLine("嚴重異常: 無法關閉本地DB {0} 的連接。", _connName); exp.ToString(); } finally { _conn = null; } } } } #endregion #region GetConn public static SqliteConn GetInstance() { return instance; } public SQLiteConnection GetConnection(string name) { SQLiteConnection _conn = connPool[name]; try { if (_conn != null) { Console.WriteLine("TRY GET LOCK"); //加鎖,直到釋放前,其它線程無法得到conn rwl[name].AcquireWriterLock(3000); Console.WriteLine("LOCK GET"); return _conn; } } catch (Exception exp) { Console.WriteLine("===GET CONN ERR====\r\n{0}", exp.StackTrace); } return null; } public void ReleaseConn(string name) { try { //釋放 Console.WriteLine("RELEASE LOCK"); rwl[name].ReleaseLock(); } catch (Exception exp) { Console.WriteLine("===RELEASE CONN ERR====\r\n{0}", exp.StackTrace); } } public SQLiteConnection GetConnection() { return GetConnection(DEFAULT_NAME); } public void ReleaseConn() { ReleaseConn(DEFAULT_NAME); } #endregion } } ////////////////////////
調用的代碼如下:
SQLiteConnection conn = null; try { conn = SqliteConn.GetInstance().GetConnection(); //在這里寫自己的代碼 } finally { SqliteConn.GetInstance().ReleaseConn(); }
值得注意的是,每次申請連接后,必須使用ReleaseConn方法釋放,否則其它線程就再也無法得到連接了。
安全起見,在作者寫的這個工具類中,啟用了最嚴格的讀寫鎖限制(即在寫入時無法讀?。H绻麛?shù)據(jù)讀取頻繁,讀者亦可開發(fā)一個得到只讀連接的方法以提高性能。
在Winxp/Win7/Win8/Win8.1 32/64位下測試通過。
更多關于C#相關內容感興趣的讀者可查看本站專題:《C#程序設計之線程使用技巧總結》、《C#操作Excel技巧總結》、《C#中XML文件操作技巧匯總》、《C#常見控件用法教程》、《WinForm控件用法總結》、《C#數(shù)據(jù)結構與算法教程》、《C#數(shù)組操作技巧總結》及《C#面向對象程序設計入門教程》
希望本文所述對大家C#程序設計有所幫助。
上一篇:C#驗證碼問題的快速解決方法
欄 目:C#教程
下一篇:C#獲取機器碼的方法詳解(機器名,CPU編號,硬盤編號,網(wǎng)卡mac等)
本文標題:C#解決SQlite并發(fā)異常問題的方法(使用讀寫鎖)
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/6357.html
您可能感興趣的文章
- 01-10關于ASP網(wǎng)頁無法打開的解決方案
- 01-10C#刪除只讀文件或文件夾(解決File.Delete無法刪除文件)
- 01-10C# readnodefile()不能讀取帶有文件名為漢字的osg文件解決方法
- 01-10c#讀寫App.config,ConfigurationManager.AppSettings 不生效的解決方法
- 01-10ASP.NET MVC命名空間時引起錯誤的解決方法
- 01-10當用戶退出點擊瀏覽器后退仍可回到原來頁面的解決方案
- 01-10C#解析json字符串總是多出雙引號的原因分析及解決辦法
- 01-10C#進階系列 WebApi身份認證解決方案推薦:Basic基礎認證
- 01-10vista和win7在windows服務中交互桌面權限問題解決方法:穿透Sessi
- 01-10SMTP客戶端未通過身份驗證等多種錯誤解決方案分享


閱讀排行
本欄相關
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻 器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實例總結
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10SublimeText編譯C開發(fā)環(huán)境設置