5

私が維持しているいくつかのレガシーコードは、無限ループに陥っています(したがって、私自身もその中にいるようです)。ただし、理由/方法がわかりません。

メイン フォーム (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 <= this one is also seen

        if (error == ERROR_ALREADY_EXISTS)
        {
            ReleaseMutex(mutexHandle);

            IntPtr hWnd = FindWindow("#NETCF_AGL_BASE_", null);
            if ((int) hWnd > 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 のコンストラクターは、(glorified の反対は?) DBConnection.GetInstance()という名前のシングルトン メソッドを呼び出します。

コード別紙 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

これがその「美化された」一種/一種のシングルトンメソッドです。

コード別紙 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 がインスタンス化されるため、そのコンストラクターが呼び出されます。

コード別紙 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()* が表示され (特に明記されていない限り)、次に Code Exhibit B、次に Code Exhibit C、次に Code Exhibit D についても同様であり、C と D の間を行ったり来たりする」牛が帰ってくるまで。」

DBConnection コンストラクターと DBConnection GetInstance() が相互に再帰的に呼び出される理由はわかりませんが、干し草の山に針が 1 つ欠けているのでしょうか、それとも見えないところに象が隠れているのでしょうか? または ...?? ?

アップデート

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

私が追加したキャッチされていない例外コード:

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

非常に興味深い - MessageBox.Show (または 2 つ) を GetFormTitle に追加した後:

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 メッセージ表示の途中で、例外が挿入されます! 完全にペンシルベニア ヒップホップ (キー ラップ) です。

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

リモート デスク デバッグ、LB2 の最高のショーでした。

4

1 に答える 1

6

これがおそらく起こっていることです(この時点では、OPが確認できるまでの理論です)

問題の始まりは…

無限ループ チェーンを開始する問題はobjCon.Open();、別紙 D にある可能性があります。おそらく、データベースへの接続に何らかの問題があり、Open()呼び出しによって例外がスローされます。もちろん、これはcatchその行の直後にあるローカルに引っ掛かります。

更新 1 に表示されているローカルcatchコールSSCS.ExceptionHandler。無害に見えますがGetFormTitle、更新 2 に表示されている名前で犯人の共犯者を隠しています。

事態が悪化するところ...

GetFormTitle非常に興味深いコードがあります。

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

...これは、データベースからユーザー情報を取得するモデルである可能性が最も高いです(他の場所)。

そして、無限ループが作成されます...

データベースから取得Userするには、接続が必要であり、おそらくDBConnection.GetInstance()呼び出され、objCon.Open();新しいサイクルが開始され、無限ループが作成されます (巧妙に、言語の組み込みループメカニズムを使用せずに、十分に注意してください)。

確認するために:

OP: 非常に単純な(つまり、 を呼び出さないGetFormTitleでください)メッセージ ボックスを に配置してくださいGetFormTitle。上記の理論が正しければ、実行パスに表示されます。

于 2014-05-02T22:21:58.680 に答える