【问题标题】:Why do my database commands only work when I interrupt them with MessageBox.Show() calls?为什么我的数据库命令只有在我用 MessageBox.Show() 调用中断它们时才起作用?
【发布时间】:2014-10-16 23:33:30
【问题描述】:

使用下面的代码,实际上只有第一组数据库命令被执行(一个表被删除,其他表删除了一条记录)如果在 DropTablesAndDeleteFromTables() 开头调用 MessageBox.Show()被注释掉了。

如果我取消注释,这样用户必须在每组数据库操作后关闭(显然不是我希望客户使用的版本),一切都很好 - 所有表都被删除,并且引用他们根据需要删除。为什么以这种方式中断进程(computus interruptus?)会影响成功与失败,我怎样才能吃到我的馅饼(让所有数据库命令成功而不用 N MessageBox.Show 打扰用户) () 要关闭的对话框?

private void DropTablesAndDeleteFromTables(string recordType, string fileName)
{
    MessageBox.Show(String.Format("In DropTablesAndDeleteFromTables(), recordType is {0}, fileName is {1}", recordType, fileName)); //TODO: Remove
    try
    {
        WorkFiles wrkFile = new WorkFiles();
        int tableOK = 0;

        DataSet workfiles;
        tableOK = wrkFile.isValidWorkTable(); 

        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)
            {
                string tmpType = row["fileType"].ToString();
                if (tmpType.EndsWith("0") || tmpType.EndsWith("1"))
                {
                    tmpType = tmpType.Substring(0, 3);
                }
                string tmpStr = row["Name"].ToString();
                int intSite = (int) row["siteNo"];
                string tmpName = tmpType + "_" + intSite.ToString() + "_" + tmpStr;

                if (tmpType != recordType) continue;
                if (tmpName != fileName) continue;

                //Drop workTables table from site-specific DB [ such as from HHSDB003.SDF ]

                String dropTable = "DROP TABLE " + tmpType + tmpStr;
                String delWorkTableSimple = string.Format("DELETE FROM workTables WHERE filetype = '{0}' and Name = '{1}'", tmpType, tmpStr);
                String delWorkTable0 =  "DELETE FROM workTables WHERE filetype = '" + tmpType + "0' and Name = '" + tmpStr + "'";
                String delWorkTable1 =  "DELETE FROM workTables WHERE filetype = '" + tmpType + "1' and Name = '" + tmpStr + "'";
                // Do site-specific database first
                // 0) Drop the table whose contents have been sent
                SendCommandToDB(dropTable, intSite, true);

                PauseThatRefreshes();

                // 1) Delete record from site-specific [ HHSDB[siteNum].SDF workTables, such as HHSDB003.SDF ]
                SendCommandToDB(delWorkTableSimple, intSite, true);

                PauseThatRefreshes();

                // Bypassing the "0" and "1" tables did nothing - still only drops one table and deletes
                // 2) Same as 1, but for table named [DSD,INV}0_Bla
                SendCommandToDB(delWorkTable0, intSite, true);

                PauseThatRefreshes();

                // 3) Same as 2, but for table named [DSD,INV}1_Bla instead of  [DSD,INV}0_Bla
                SendCommandToDB(delWorkTable1, intSite, true);

                PauseThatRefreshes();

                // Four calls to site-specific above; Three-four calls to NON-site-specific below

                // 4) Delete record from NON-site-specific [ HHSDB[siteNum].SDF workTables, such as HHSDB003.SDF ]
                SendCommandToDB(delWorkTableSimple, intSite, false);

                PauseThatRefreshes();

                // 5) Same as 1, but for table named [DSD,INV}0_Bla
                SendCommandToDB(delWorkTable0, intSite, false);

                PauseThatRefreshes();

                // 6) Same as 2, but for table named [DSD,INV}1_Bla instead of  [DSD,INV}0_Bla
                SendCommandToDB(delWorkTable1, intSite, false);

                PauseThatRefreshes();

                // 7) Conditionally delete a record (if a DSD record, from DSDHeader, which is in the base (NON-site-specific) database
                if (tmpType == "DSD")
                {
                    String dml = string.Format("DELETE FROM {0}Header WHERE Name = '{1}'", tmpType, tmpStr);
                    SendCommandToDB(dml, intSite, false);                               
                }

                populateTransactionListBoxWithWorkTables();
                return;
            } // foreach (DataRow row in workfiles.Tables[0].Rows)
        } // if ( tableOK > 0) //Table exist
    //} // lock TFS#4054
} // try
catch (Exception ex)
{
        SSCS.ExceptionHandler(ex, "frmCentral.DropTablesAndDeleteFromTables");
}
} // DropTablesAndDeleteFromTables

private void PauseThatRefreshes()
{
    int j = 0;
    while (j < 100000)
    {
        j++;
    }
}

private void SendCommandToDB(String sql, int siteNum, bool SiteSpecificDB)
{
    try
    {
        if (SiteSpecificDB)
        {
            if (dbconn.InBaseDatabase())
            {
                dbconn = DBConnection.GetInstance(siteNum.ToString());
            }
        }
        else
        {
            if (!(dbconn.InBaseDatabase()))  
            {
                dbconn = DBConnection.GetInstance();
            }
        }
        dbconn.DBCommand(sql, true);
    }
    catch (SqlCeException ee)
    {
        . . .
    } 
}

有什么解决方法可以在不强制用户在游戏中扮演角色的情况下让流程浮出水面?

更新

这似乎是每组数据库操作之间经过多少时间的问题。当我改变这个时:

while (i < 100000)

...在 PauseThatRefreshes() 中对此:

while (i < 10000000)

(将 MessageBox.Show() 注释掉)它起作用了!但这仍然让我感到紧张。有没有更“科学”(优雅?)的方式来实现这一点?

【问题讨论】:

    标签: c# sql-server-ce compact-framework windows-ce messagebox


    【解决方案1】:

    您的代码示例既太复杂又不完整。所以我不能确定出了什么问题。

    但症状是一个典型的迹象,表明您 a) 在主 GUI 线程上运行有问题的代码,并且 b) 该代码在某些时候最终被阻塞,等待主 GUI 线程执行其他操作(即死锁)。

    修复它的正确方法是在不同于主 GUI 线程的线程上执行这些操作。这很可能会在您从操作中访问 GUI 元素时引入新问题,您必须使用 GUI API 的“调用”机制来解决这些问题。

    【讨论】:

    • 这解释了整个代码中散布的所有神秘、疯狂的科学家背景线程。解释,不原谅(以我的思维方式 - 至少不是以令人讨厌的方式完成,没有任何文件说明做了什么以及为什么。
    • 也就是说,根据你的更新——扩展你的空闲循环“修复”了问题——你可能根本没有处理 GUI 死锁。这听起来更像是您以某种方式耗尽了数据库连接资源,或者当您尝试在太短的时间内执行太多 SQL 操作时,它们被占用了。尽管如此,一个适当的简洁但完整的代码示例将在很大程度上帮助我们其他人弄清楚实际问题是什么。如果在非 GUI 线程上运行此操作可以修复它,那很好……但我不相信它会。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-06
    • 2021-05-08
    • 2021-09-01
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 2015-04-29
    相关资源
    最近更新 更多