4

私は、プログラムとプログラムが実行されているコンピューターの外部のさまざまなリソースを照会して変更する既存の C# プログラムに取り組んでいます。このプログラムはほとんどのコンピューターで動作しますが、ランダムなコンピューターでは頻繁に失敗します。これが発生した場合、ユーザーが画面にスローされた例外についてユーザーが私たちに伝えたこと以外に、理由についてのフィードバックはありません。彼らが私たちのために画面にそれを残したとしても、それは私たちにほとんどまたはまったく有用な情報を提供しません. その後、特定のイベントをログに記録するようにプログラムを修正し、情報をテキスト ファイルに収集しました。これを使用して、プログラムが停止した場所を概算できます。これは少なくとも最初の一歩ですが、stackoverflow で多くのスレッドを読み取ることからです。

現在、すべての to do コードを囲む大きな try ブロックがあり、それぞれの末尾に catch ブロックが 1 つだけあります。

private void method_name()
{
    try
    {
       //many lines of to do code calling many other methods
    }
    catch (exception ex)
    {
        MessageBox.Show("An Error has occurred in method_name() :" + ex.Message);
    }

私が最初に考えたのは、より大きな try ブロック内により具体的な try/catch ブロックをネストすることでしたが、さまざまなコンテキストで変数が到達不能になるという問題に直面し続けています。例えば

try
{
   LdapConnection ldapConn = new LdapConnection();
   ldapConn.Connect(details of connection);
   ldapConn.Bind(details of bind statement);
   LdapSearchQueue queue = ldapConn.Search(search criteria and such);
   LdapMessage message;
}
catch (somesortofexception ex)
{
   //do something sensible about it
}

while ((message = queue.getResponse()) != null)
{
   //do things with message
}
ldapConn.Disconnect();

問題は、try ブロックの外ではメッセージとキューに到達できないことです。これは、私が作業しようとしている「//他の多くのメソッドを呼び出す to do コードの多くの行」で行われたことのほんの一例です。

だからここに私の質問があります:

上記の例で try ブロックを大きくして while ループと LDAP 切断を含めるか、大きな try ループをそのままにして、その間に発生することのリストを作成し、最後に多くの catch ブロックを作成する方がよいでしょうか。特定の例外をキャッチするには?このサイトで読んだ内容に基づいて、特定のコードの周りに小さな try ブロックを配置する方法だと思います。

私が実装しようとしているように、より小さな try ブロックを使用する必要があります。コードの小さなスニペット内で発生した例外をキャッチしてログ ファイルに記録する catch ブロックを使用するだけで問題ありません。または、試してキャッチする必要があります。特定の例外?とにかくファイルにログを記録する以外に、これらの例外でできることは他にありません。

例外をスローする必要がありますか? 何か問題が発生したことを伝え、IT に連絡するようにという平易な英語のメッセージ以外に、ユーザーに何かが飛び交うことは本当に望んでいません。現在、catch ブロックは何もスローしません。

4

2 に答える 2

0

例外の分解については、常に接続コードをクエリコードから分離します。

したがって、これは次のようになります。

LdapConnection ldapConn = new LdapConnection();
try
{
   ldapConn.Connect(details of connection);
   ldapConn.Bind(details of bind statement);
}
catch (somesortofexception ex)
{
   //Log, send error message..
   ldapConn = null;
}

if (ldapConn != null)
{
    try
    {
         //Do what you need with your connection
    }
    catch (Exception ex)
    {
         //Log, Error....
    }
    finally
    {
        //Disconnect your ldap here
    }
}

理想的には、すべての接続コードと検索コードを別々のメソッドに配置するので、より良いスタックトレースが得られます。

エラーメッセージについて私はまた、いくつかの一般的なメッセージを使用し、例外の詳細をある種のファイル(http://logging.apache.org/log4net/)に記録することは、適切にフォーマットされたログファイルを作成するのに非常に便利です。

于 2012-09-20T17:05:11.110 に答える
0

特定の例外を飲み込むローカルの catch ブロックは、その例外が予期されていて、ローカルで処理できる限り問題ありません。この場合、例外に含まれるもののみに基づいてユーザーに情報を提供できます。または、ロギングやメッセージに状態を含めたい場合は、変数定義を try ブロックの上に移動できます。

予期しない例外については、プログラムを正常に終了する前に、グローバル ハンドラーによってログに記録できるように、コール スタックの一番上までバブルを発生させる必要があります。これらの例外を飲み込んで、死体を直立姿勢で釘付けにする可能性は望ましくありません。

これが WinForms アプリであると仮定すると、グローバル ハンドラーのセットアップは次のようになります。

public static void Main(string[] args)
{
    // Switch-off the Windows Forms default handler for unhandled exceptions.
    // NB From .NET 4 upwards, this won't work if the process state is corrupted.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Setup event handler to intercept an unhandled exception on a UI thread.
    // NB The exception will still terminate the application. 
    // But you can show a MessageBox and/or log the exception. 
    Application.ThreadException += 
        new ThreadExceptionEventHandler(App_UiThreadException);

    // Setup event handler to intercept unhandled exception on a non-UI thread.
    AppDomain.CurrentDomain.UnhandledException += new 
        UnhandledExceptionEventHandler(App_NonUiThreadException);

    // Run the application (open main form etc).    
}
于 2012-09-20T17:02:21.337 に答える