C#解決SQlite並發異常問題的方法(使用讀寫鎖)_C#教程

來源:互聯網
上載者:User

本文執行個體講述了C#解決SQlite並發異常問題的方法。分享給大家供大家參考,具體如下:

使用C#訪問sqlite時,常會遇到多線程並發導致SQLITE資料庫損壞的問題。

SQLite是檔案層級的資料庫,其鎖也是檔案層級的:多個線程可以同時讀,但是同時只能有一個線程寫。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  // 手動控制銷毀,保證資料完整性  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方法釋放,否則其它線程就再也無法得到串連了。

安全起見,在作者寫的這個工具類中,啟用了最嚴格的讀寫鎖限制(即在寫入時無法讀取)。如果資料讀取頻繁,讀者亦可開發一個得到唯讀串連的方法以提高效能。

在Winxp/Win7/Win8/Win8.1 32/64位下測試通過。

更多關於C#相關內容感興趣的讀者可查看本站專題:《C#程式設計之線程提示總結》、《C#操作Excel技巧總結》、《C#中XML檔案操作技巧匯總》、《C#常見控制項用法教程》、《WinForm控制項用法總結》、《C#資料結構與演算法教程》、《C#數組操作技巧總結》及《C#物件導向程式設計入門教程》

希望本文所述對大家C#程式設計有所協助。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.