如何解决c#操作Access数据库时出现的“无法更新,当前被锁定”问题

1.目前正在用c#写一个上位机软件,需要每隔10秒备份一次数据,将数据写入一个名为“SpeedDB.mdb”的Access数据中。上位机软件与下位机通过tcp连接,单独使用了一个线程来进行每隔10秒的数据备份,程序第一次启动时运行没问题,当tcp连接断开后终止此线程,重新连接后再实例化并启动此线程,此时便会出现这个异常,提示“无法更新,当前被锁定”。同时还会导致整个程序其它操作变卡。

2.代码如下:
(1)每次tcp连接上时会实例化并启动数据备份的线程

SpeedDBThread = new Thread(new ThreadStart(AddSpeedDB)) 
{
   IsBackground = true        
};//实例化转速备份线程

SpeedDBThread.Start();          //启动转速备份线程

(2)数据备份的函数如下:

private void AddSpeedDB()
        {
            OleDbConnection ODbCon = new OleDbConnection("Provider = Microsoft.Jet.OLEDB.4.0;Data Source = D:\\SpeedDB.mdb");   //用连接字符串初始化OleDbConnection的实例对象ODbCon
            while (true)    
            {
                if(tcpClient != null && tcpClient.Connected == true)    //仅在连接时备份
                {
                    try
                    {
                        ODbCon.Open();      //调用Open方法打开数据库连接
                        string TimeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");  //获取此次转速备份的时间

                        //写入数据
                        for (UInt16 JDZ_NUM = 1; JDZ_NUM <= 12; JDZ_NUM++)
                        {
                            for (UInt16 ZJ_NUM = 1; ZJ_NUM <= 20; ZJ_NUM++)
                            {
                                for (UInt16 JQ_NUM = 1; JQ_NUM <= 20; JQ_NUM++)
                                {
                                    OleDbCommand AddRecordCommand = new OleDbCommand()
                                    {
                                        Connection = ODbCon
                                    };
                                    if (AllSpeed_NormalMsg[JDZ_NUM - 1, ZJ_NUM - 1].uFrame != 0)
                                    {
                                        AddRecordCommand.CommandText = string.Format(DataBase.SpeedInfo_InsertStr, TimeStr,
                                            (AllSpeed_NormalMsg[JDZ_NUM - 1, ZJ_NUM - 1].uGroup - 1) * 400 +
                                            (AllSpeed_NormalMsg[JDZ_NUM - 1, ZJ_NUM - 1].uFrame - 1) * 20 + JQ_NUM,
                                            AllSpeed_NormalMsg[JDZ_NUM - 1, ZJ_NUM - 1].Info[JQ_NUM - 1].uSpeed);
                                        AddRecordCommand.ExecuteNonQuery();
                                    }
                                    else
                                    {
                                        AddRecordCommand.CommandText = string.Format(DataBase.SpeedInfo_InsertStr, TimeStr,
                                            (JDZ_NUM - 1) * 400 + (ZJ_NUM - 1) * 20 + JQ_NUM, 9.99);
                                        AddRecordCommand.ExecuteNonQuery();
                                    }
                                }
                            }
                        }
                        Thread.Sleep(1000);
                        ODbCon.Close();     //关闭数据库连接
                        Thread.Sleep(9000);
                    }
                    catch (Exception ex)
                    {
                        //异常提示
                        Current_Inform.Items.Insert(0, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "转速备份异常:" + ex.Message);
                        SpeedDBThread.Start();
                    }
                }
                else
                {
                    ODbCon.Close();
                    SpeedDBThread.Abort();  //无连接时终止线程
                    Thread.Sleep(1);

                }


            }
        }

3.可以看到代码里面都确定每次打开数据库连接最后都用ODbCon.Close();关闭了,但还是会有这个问题,我尝试过在捕获的异常处理中重启这个线程,代码如下:

catch (Exception ex)
                    {
                        //异常提示
                        Current_Inform.Items.Insert(0, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "转速备份异常:" + ex.Message);
                        ODbCon.Close();     //关闭数据库连接
                        GC.Collect();
                        Thread.Sleep(1);
                        SpeedDBThread.Abort();  //先终止此线程
                        Thread.Sleep(3000);

                        //重启线程
                        SpeedDBThread = new Thread(new ThreadStart(AddSpeedDB))             //实例化转速备份线程
                        {
                            IsBackground = true        //设置为后台线程
                        };
                        SpeedDBThread.Start();
                    }

还是会出现问题,并且会有新的异常提示“正在终止线程”。

目前很急,希望各位大佬看看能不能解决这个问题,拜托了!

https://zhidao.baidu.com/question/1238365905018214299.html

希望能帮到你.
bool isCancel = false;
private void AddSpeedDB()
{
OleDbConnection ODbCon = new OleDbConnection("Provider = Microsoft.Jet.OLEDB.4.0;Data Source = D:\SpeedDB.mdb"); //用连接字符串初始化OleDbConnection的实例对象ODbCon
while (!isCancell)
{
if (tcpClient != null && tcpClient.Connected == true) //仅在连接时备份
{
try
{
ODbCon.Open(); //调用Open方法打开数据库连接
string TimeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //获取此次转速备份的时间

                    //写入数据
                    for (UInt16 JDZ_NUM = 1; JDZ_NUM <= 12; JDZ_NUM++)
                    {
                        for (UInt16 ZJ_NUM = 1; ZJ_NUM <= 20; ZJ_NUM++)
                        {
                            for (UInt16 JQ_NUM = 1; JQ_NUM <= 20; JQ_NUM++)
                            {
                                OleDbCommand AddRecordCommand = new OleDbCommand()
                                {
                                    Connection = ODbCon
                                };
                                if (AllSpeed_NormalMsg[JDZ_NUM - 1, ZJ_NUM - 1].uFrame != 0)
                                {
                                    AddRecordCommand.CommandText = string.Format(DataBase.SpeedInfo_InsertStr, TimeStr,
                                        (AllSpeed_NormalMsg[JDZ_NUM - 1, ZJ_NUM - 1].uGroup - 1) * 400 +
                                        (AllSpeed_NormalMsg[JDZ_NUM - 1, ZJ_NUM - 1].uFrame - 1) * 20 + JQ_NUM,
                                        AllSpeed_NormalMsg[JDZ_NUM - 1, ZJ_NUM - 1].Info[JQ_NUM - 1].uSpeed);
                                    AddRecordCommand.ExecuteNonQuery();
                                }
                                else
                                {
                                    AddRecordCommand.CommandText = string.Format(DataBase.SpeedInfo_InsertStr, TimeStr,
                                        (JDZ_NUM - 1) * 400 + (ZJ_NUM - 1) * 20 + JQ_NUM, 9.99);
                                    AddRecordCommand.ExecuteNonQuery();
                                }
                            }
                        }
                    }
                    Thread.Sleep(1000);
                    ODbCon.Close();     //关闭数据库连接
                    Thread.Sleep(9000);
                }
                catch (Exception ex)
                {
                    //异常提示
                    Current_Inform.Items.Insert(0, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "转速备份异常:" + ex.Message);
                    isCancel = true;


                    ODbCon.Close();
                    try
                    {
                        isCancel = true;
                        SpeedDBThread.Abort();  //无连接时终止线程,这里最好先循环停下来,因为 Abort 不一定能正常停下来.
                    }
                    catch (Exception)
                    {
                        Thread.ResetAbort();
                        SpeedDBThread.Start(); //重新启动,我觉得还是重新的去new 一个 thread 更靠谱。
                    }


                    Thread.Sleep(1);

                }
            }
            else
            {
                ODbCon.Close();
                try
                {
                    isCancel = true;
                    SpeedDBThread.Abort();  //无连接时终止线程,这里最好先循环停下来,因为 Abort 不一定能正常停下来.
                }
                catch (Exception)
                {
                    Thread.ResetAbort();
                }


                Thread.Sleep(1);

            }


        }
    }

数据库被占用了,你需要把其他调用这个数据库的链接断掉就可以了。你这个写法只适合单用户使用数据库