欧美大屁股bbbbxxxx,狼人大香伊蕉国产www亚洲,男ji大巴进入女人的视频小说,男人把ji大巴放进女人免费视频,免费情侣作爱视频

歡迎來(lái)到入門(mén)教程網(wǎng)!

C#教程

當(dāng)前位置:主頁(yè) > 軟件編程 > C#教程 >

C#解決SQlite并發(fā)異常問(wèn)題的方法(使用讀寫(xiě)鎖)

來(lái)源:本站原創(chuàng)|時(shí)間:2020-01-10|欄目:C#教程|點(diǎn)擊: 次

本文實(shí)例講述了C#解決SQlite并發(fā)異常問(wèn)題的方法。分享給大家供大家參考,具體如下:

使用C#訪問(wèn)sqlite時(shí),常會(huì)遇到多線程并發(fā)導(dǎo)致SQLITE數(shù)據(jù)庫(kù)損壞的問(wèn)題。

SQLite是文件級(jí)別的數(shù)據(jù)庫(kù),其鎖也是文件級(jí)別的:多個(gè)線程可以同時(shí)讀,但是同時(shí)只能有一個(gè)線程寫(xiě)。Android提供了SqliteOpenHelper類,加入Java的鎖機(jī)制以便調(diào)用。但在C#中未提供類似功能。

作者利用讀寫(xiě)鎖(ReaderWriterLock),達(dá)到了多線程安全訪問(wèn)的目標(biāo)。

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
  // 使用單例,解決初始化與銷毀時(shí)的問(wèn)題
  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
  // 手動(dòng)控制銷毀,保證數(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("關(guān)閉本地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("嚴(yán)重異常: 無(wú)法關(guān)閉本地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");
        //加鎖,直到釋放前,其它線程無(wú)法得到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
}
}
////////////////////////

調(diào)用的代碼如下:

SQLiteConnection conn = null;
try
{
  conn = SqliteConn.GetInstance().GetConnection();
  //在這里寫(xiě)自己的代碼
}
finally
{
  SqliteConn.GetInstance().ReleaseConn();
}

值得注意的是,每次申請(qǐng)連接后,必須使用ReleaseConn方法釋放,否則其它線程就再也無(wú)法得到連接了。

安全起見(jiàn),在作者寫(xiě)的這個(gè)工具類中,啟用了最嚴(yán)格的讀寫(xiě)鎖限制(即在寫(xiě)入時(shí)無(wú)法讀?。H绻麛?shù)據(jù)讀取頻繁,讀者亦可開(kāi)發(fā)一個(gè)得到只讀連接的方法以提高性能。

在Winxp/Win7/Win8/Win8.1 32/64位下測(cè)試通過(guò)。

更多關(guān)于C#相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《C#程序設(shè)計(jì)之線程使用技巧總結(jié)》、《C#操作Excel技巧總結(jié)》、《C#中XML文件操作技巧匯總》、《C#常見(jiàn)控件用法教程》、《WinForm控件用法總結(jié)》、《C#數(shù)據(jù)結(jié)構(gòu)與算法教程》、《C#數(shù)組操作技巧總結(jié)》及《C#面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》

希望本文所述對(duì)大家C#程序設(shè)計(jì)有所幫助。

網(wǎng)頁(yè)制作CMS教程網(wǎng)絡(luò)編程軟件編程腳本語(yǔ)言數(shù)據(jù)庫(kù)服務(wù)器

如果侵犯了您的權(quán)利,請(qǐng)與我們聯(lián)系,我們將在24小時(shí)內(nèi)進(jìn)行處理、任何非本站因素導(dǎo)致的法律后果,本站均不負(fù)任何責(zé)任。

聯(lián)系QQ:835971066 | 郵箱:835971066#qq.com(#換成@)

Copyright © 2002-2020 腳本教程網(wǎng) 版權(quán)所有