这是如何导致无限循环的?

我保留的一些遗留代码卡在无限循环中(因此我自己似乎在一个); 但我无法弄清楚为什么/怎么做。

这是应用程序的入口点,它实例化主窗体(frmCentral):

代码展览A.

public static int Main(string [] args) { try { AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler); string name = Assembly.GetExecutingAssembly().GetName().Name; MessageBox.Show(string.Format("Executing assembly is {0}", name)); // TODO: Remove after testing <= this one is seen IntPtr mutexHandle = CreateMutex(IntPtr.Zero, true, name); long error = GetLastError(); MessageBox.Show(string.Format("Last error int was {0}", error.ToString())); // TODO: Remove after testing  0) { SetForegroundWindow(hWnd); } return 0; } MessageBox.Show("made it into Main method #4"); // TODO: Remove after testing <= this one is seen ReleaseMutex(mutexHandle); MessageBox.Show("made it into Main method #5"); // TODO: Remove after testing <= this one is seen DeviceInfo devIn = DeviceInfo.GetInstance(); MessageBox.Show("made it into Main method #6"); // TODO: Remove after testing <= this one is seen Wifi.DisableWifi(); MessageBox.Show("made it into Main method #7"); // TODO: Remove after testing <= this one is seen // Instantiate a new instance of Form1. frmCentral f1 = new frmCentral(); f1.Height = devIn.GetScreenHeight(); f1.Text = SSCS.GetFormTitle("SSCS HHS", "", ""); MessageBox.Show("made it before Application.Run() in Main method"); // TODO: Remove after testing <= this one is NOT seen Application.Run(f1); devIn.Close(); Application.Exit(); return 0; } catch(Exception ex) { SSCS.ExceptionHandler(ex, "Main"); return 0; } } // Main() method 

frmCentral的构造函数然后调用一个名为DBConnection.GetInstance()的单例方法与glorified相反的是什么?

CODE EXHIBIT B

 public frmCentral() { try { // // Required for Windows Form Designer support // InitializeComponent(); MessageBox.Show("made it past InitializeComponent() in frmCentral constructor"); // <= this displays devIn = DeviceInfo.GetInstance(); MessageBox.Show("made it past DeviceInfo.GetInstance() in frmCentral constructor"); // <= this displays dbconn = DBConnection.GetInstance(); MessageBox.Show("made it past DBConnection.GetInstance() in frmCentral constructor"); WindowState = FormWindowState.Maximized; UpdateMenuItemSelectable = false; ResetConnectionFetchForm = false; AllowNewItems = true; listboxWork.Focus(); MessageBox.Show("made it through frmCentral constructor"); // <= this one does NOT display } catch (Exception ex) { SSCS.ExceptionHandler(ex, "frmCentral()"); } } // frmCentral Constructor 

这是“美化的”单一/种类的单身方法:

CODE EXHIBIT C

 // Singleton pattern, or at least a derivation thereof public static DBConnection GetInstance() { MessageBox.Show("made it into DBConnection.GetInstance()"); try { if (instance == null) { MessageBox.Show("made it into DBConnection.GetInstance(); instance was null"); instance = new DBConnection(); } } catch(Exception ex) { SSCS.ExceptionHandler(ex, "DBConnection.GetInstance"); } return instance; } 

这实例化了DBConnection,因此调用了它的构造函数:

CODE EXHIBIT D

 private DBConnection() { try { // Connection String string conStr = "Data Source = " + filename; string cmpStr = conStr + ".tmp"; MessageBox.Show(string.Format("made it into DBConnection constructor. cmpStr == {0}", cmpStr)); // TODO: Comment out or remove if (File.Exists(filename+".tmp")) File.Delete(filename+".tmp"); engine = new SqlCeEngine(conStr); MessageBox.Show(string.Format("SqlCeEngine created. conStr == {0}", conStr)); // TODO: Comment out or remove if (File.Exists(filename)) { MessageBox.Show(string.Format("file {0} exists", filename)); // TODO: Comment out or remove } else { // Create the SQL Server CE database engine.CreateDatabase(); MessageBox.Show("Made it past call to engine.CreateDatabase()"); // TODO: Comment out or remove } engine.Dispose(); objCon = new SqlCeConnection(conStr); MessageBox.Show("Made it past call to new SqlCeConnection(conStr)"); // TODO: Comment out or remove objCon.Open(); } catch(Exception ex) { SSCS.ExceptionHandler(ex, "DBConnection.DBConnection"); } } 

我从Code Exhibit A看到了* MessageBox.Show()* s(除非另有说明),然后是Code Exhibit B,然后是Code Exhibit C,然后是Code Exhibit D,然后它在C和D之间来回转换“直到奶牛回家。“

我不明白为什么DBConnection构造函数和DBConnection GetInstance()以递归方式相互调用,但是……我在大海捞针中是否有针,或是隐藏在普通视野中的大象,还是……? ?

UPDATE

 public static void ExceptionHandler(Exception ex, string location) { try { MessageBox.Show("Exception: " + ex.Message + "\n\nLocation: " + location, GetFormTitle("SSCS: " + ex.GetType().FullName,"","")); } catch(Exception exc) { MessageBox.Show("Exception Handler generated an exception!\n" + exc.Message + "\n\nCalling Location: " + location, GetFormTitle("SSCS: " + exc.GetType().FullName,"","")); } } 

更新2

这是更有启发性的晦涩:

 public static string GetFormTitle(string formName, string serialNo, string siteNo) { string titleBar = formName == "" ? "SSCS HHS" : formName; if((serialNo == "")) { User person = new User(); person.getUserFromTable(); serialNo = person.getSerialNo(); } if (frmCentral.HashSiteMapping.ContainsKey(siteNo)) { siteNo = (string) frmCentral.HashSiteMapping[siteNo]; } if (serialNo != "") titleBar += " - " + serialNo + (siteNo == "" ? "" : " Site #" + siteNo); return titleBar; } 

更新3

我添加的未捕获的exception代码:

 currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler); static void GlobalExceptionHandler(object sender, UnhandledExceptionEventArgs args) { Exception e = (Exception)args.ExceptionObject; MessageBox.Show(string.Format("GlobalExceptionHandler caught {0}; Compact Framework Version == {1}", e.Message, Environment.Version.ToString())); } 

我还没有看到任何证据表明这个处理程序已经到达(无论如何,到目前为止)。

更新4

非常有趣 – 在向GetFormTitle添加MessageBox.Show(或两个)之后:

 public static string GetFormTitle(string formName, string serialNo, string siteNo) { MessageBox.Show(string.Format("GetFormTitle() reached. formName == {0}; serialNo == {1}; siteNo == {2}", formName, serialNo, siteNo)); // TODO: Remove after testing string titleBar = formName == "" ? "SSCS HHS" : formName; if((serialNo == "")) { User person = new User(); person.getUserFromTable(); serialNo = person.getSerialNo(); } if (frmCentral.HashSiteMapping.ContainsKey(siteNo)) { siteNo = (string) frmCentral.HashSiteMapping[siteNo]; } if (serialNo != "") titleBar += " - " + serialNo + (siteNo == "" ? "" : " Site #" + siteNo); MessageBox.Show(string.Format("titleBar val about to be returned. Val is {0}", titleBar)); // TODO: Remove after testing return titleBar; } 

…这些是我现在看到的MessageBox.Show()的序列:

 0) Made it into DBConnection.GetInstance() 1) Made it into DBConnection.GetInstance() instance was null 2) Made it to DBConnection constructor cmpStr == .... 3) Sqlceengine created. conStr == ... 4) File \My Documents\HHSDB.SDF exists 5) Made it past call to new SqlCeConnection(conStr) 6) GetFormTitle() reached. fromName == SSCS: System.Data.SqlserverCe.SqlCeException; serial No ==; siteNo == 

…接下来是一轮追尾,递归的消息,直到我热身启动(我讨厌与Fab 4相矛盾,但与流行的观点相反,幸福绝对不是热情的启动!*)

…所以正好在MessageBox消息显示中插入exception! 全宾夕法尼亚嘻哈(Key Rap)!

 * Let's have no attempts at humor revolving around warm booty, now! 

这是远程桌面调试的最佳展示,LB2!

这是可能发生的事情(在此之前是一个理论,直到OP可以确认)

启动问题的事情……

启动无限循环链的问题可能是objCon.Open(); 在图表D中。连接到数据库可能存在一些问题, Open()调用应该抛出exception。 这当然会被紧随该行之后的本地catch

本地catch调用SSCS.ExceptionHandler ,它显示在Update 1中。它看起来很温和,但是它隐藏了罪魁祸首的帮凶,名称GetFormTitle显示在Update 2中。

事情变得更糟……

GetFormTitle有一段非常有趣的代码:

 User person = new User(); person.getUserFromTable(); 

…最有可能是从数据库中检索用户信息的模型(其他地方)。

因此创建了无限循环……

好吧,要从数据库中获取User ,需要一个连接,这很可能导致调用DBConnection.GetInstance() ,这将转到objCon.Open(); 它开始新的循环,因此创建了一个无限循环 (巧妙地,不使用任何语言的内置循环机制,需要适当注意)。

确认:

OP:请把非常简单(意思是没有调用GetFormTitle ,请) GetFormTitle MessageBoxes,如果上述理论是正确的,你会在执行路径中看到它。