C# 如何暂停SQLCE查询,直到它所查询的表不再被其他地方访问?

C# 如何暂停SQLCE查询,直到它所查询的表不再被其他地方访问?,c#,sql-server-ce,compact-framework,windows-ce,reentrancy,C#,Sql Server Ce,Compact Framework,Windows Ce,Reentrancy,我有一个查询表中记录数的方法。QA发现了一种“边缘情况”,即如果以特定的顺序和速度(尽可能快)取消特定操作,GUI将“忘记”该表中的其余记录(表的内容上载到服务器;当每个表完成时,相应的表将被删除) 需要说明的是,该表中删除了记录,然后查询了计数(“工作表”),它是一个表名表,在处理完这些记录后将被删除 我确定(我很确定)当查询workTables表的记录计数时,当“workTables”表中的记录正在被删除时,就会发生这种异常。这会导致异常,这会导致方法返回-1,在我们的例子中,这表示我们应该

我有一个查询表中记录数的方法。QA发现了一种“边缘情况”,即如果以特定的顺序和速度(尽可能快)取消特定操作,GUI将“忘记”该表中的其余记录(表的内容上载到服务器;当每个表完成时,相应的表将被删除)

需要说明的是,该表中删除了记录,然后查询了计数(“工作表”),它是一个表名表,在处理完这些记录后将被删除

我确定(我很确定)当查询workTables表的记录计数时,当“workTables”表中的记录正在被删除时,就会发生这种异常。这会导致异常,这会导致方法返回-1,在我们的例子中,这表示我们应该让GUI不显示这些记录

是否有一种方法可以检查表是否正在从中删除记录,并等到操作完成后再继续查询,这样它就不会抛出异常

对于那些对细节感兴趣的人来说,这种方法就是在这些特殊情况下抛出异常的方法:

public int isValidTable(string tableName)
{
    int validTable = -1; 
    string tblQuery = "SELECT COUNT(*) FROM ";
    tblQuery += tableName;
    openConnectionIfPossibleAndNecessary();
    try
    {
        SqlCeCommand cmd = objCon.CreateCommand();
        cmd.CommandText = tblQuery;
        object objcnt = cmd.ExecuteScalar();
        validTable = Int32.Parse(objcnt.ToString());
    }
    catch (Exception ex)
    {
        validTable = -1;
    }
    return validTable;
}
…这是一种在相应表的内容上载后从“workTables”表中删除记录的方法:

private void DropTablesAndDeleteFromTables(string recordType, string fileName)
{
    try
    {
        WorkFiles wrkFile = new WorkFiles();

        int tableOK = 0;

        DataSet workfiles;
        tableOK = wrkFile.isValidWorkTable(); // -1 == "has no records"

        if (tableOK > 0) //Table has at least one record
        {
            workfiles = wrkFile.getAllRecords();

            //Go thru dataset and find filename to clean up after
            foreach (DataRow row in workfiles.Tables[0].Rows)
            {
                . . .
                dynSQL = string.Format("DELETE FROM workTables WHERE filetype = '{0}' and Name = '{1}'", tmpType, tmpStr);
                dbconn = DBConnection.GetInstance();
                dbconn.DBCommand(dynSQL, false);

                populateListBoxWithWorkTableData();
                return;
            } // foreach (DataRow row in workfiles.Tables[0].Rows)
        } 
    }
    catch (Exception ex)
    {
        SSCS.ExceptionHandler(ex, "frmCentral.DropTablesAndDeleteFromTables");
    }
} 

// method called by DropTablesAndDeleteFromTables() above
public int isValidWorkTable() //reverted to old way to accommodate old version of DBConnection
{
    // Pass the buck
    return dbconn.isValidTable("workTables");
}
我知道这个代码非常时髦、笨拙、笨拙;对其进行重构以使其更有意义并更易于理解是一个漫长而持续的过程

更新 我无法测试此代码:

lock (this)
{
  // drop the table
}
…然而,由于手持设备不再允许我向其复制文件(我得到“无法复制[filename.[dll,exe]设备已停止响应或已断开连接”(已连接,如ActiveStync所示))

如果这不起作用,我可能不得不尝试以下方法:

// global var
bool InDropTablesMethod;

// before querying that database from elsewhere:
while (InDropTablesMethod)
{
  Pause(500);
}
更新2 我终于能够测试我的锁代码(二进制文件的副本存在于内存中,不允许我覆盖它们;启动文件夹中的.exe有一个*.lnk,因此每次我启动掌上电脑时,它都试图运行有缺陷的.exe版本),但它不起作用-我仍然会遇到相同的冲突/争用

更新3 看起来有效的,尽管可能很麻烦,是:

public class CCRUtils
{
    public static bool InDropTablesMethod;
    . . .

if (CCRUtils.InDropTablesMethod) return;
CCRUtils.InDropTablesMethod = true;
    . . . // do it all; can you believe somebody from El Cerrito has never heard of CCR?
CCRUtils.InDropTableMethod = false;
更新4 写得太快-bug回来了。我添加了这个MessageBox.Show(),并且确实在运行时看到了文本“代码重入性证明”

while (HHSUtils.InDropTablesMethod)
{
    MessageBox.Show("proof of code re-entrancy");
    i++;
    if (i > 1000000) return; 
}
try
{
    HHSUtils.InDropTablesMethod = true;
    . . .               
}
HHSUtils.InDropTablesMethod = false;

…所以我猜代码重入可能是一个问题是正确的…

使用锁来序列化访问谢谢,ErikEJ;你有什么例子可以这样做吗?是的-根据这个:,我只需要“lock(this){…}”这真的那么简单吗?我在等待测试,直到我得到答案:我一直在尝试锁(“lock(this)”)到处都是,这真的没用。