2

クラスでロガー オブジェクトのようなオブジェクトを静的として定義する場合、次のようなメソッドを呼び出します。

public class Manager
{    
    private static ClientLogManager log = new ClientLogManager();

    public void Log(string Message)
    {
         log.Debug(string Message);
    }
}

これは、クラス ライブラリ プロジェクトで定義されます。

私の理解では、静的変数はこのアプリケーションのすべてのリクエスト間で共有されるため、ログ オブジェクトが共有されます。ただし、メソッド Debug 自体は静的ではありませんが、オブジェクトは静的であるため、このメソッドのインスタンスは 1 つだけになります。あれは正しいですか?

多くのユーザーが同時にこのコードを呼び出している場合、2 つのリクエストが同時に log.Debug メソッドを呼び出している場合、2 番目のリクエストのメッセージが 1 番目のリクエストのメッセージを上書きすることはありますか?

また、これをシングルトンに置き換えた方が良いでしょうか? リクエストごとに 1 つの Singleton オブジェクトではありませんか?

ここに ClientLogManager コードがあります

  public class ClientLogManager
    {
        #region Member Variables

        private static readonly ILog _log = LogManager.GetLogger(typeof(ClientLogManager));

        #endregion

        #region Constructors

        public ClientLogManager()
        {

        }

        #endregion

        #region Public Methods

        public void Debug(string message)
        {
            _log.Debug(message);
        }

        #endregion
    }
4

2 に答える 2

1

多くのユーザーが同時にこのコードを呼び出している場合、2つのリクエストが同時にlog.Debugメソッドを呼び出している場合、2番目のリクエストのメッセージが1番目のリクエストのメッセージを上書きできますか?

はい、ロガーがこれをサポートするように特別に作成されていない限り、可能です。ほとんどのロガーはこれをサポートするように設計されているため、最初から自分でロールした場合を除いて、すべての書き込みを内部で同期します(そうする必要はありません)。よくわからない場合は、使用している特定のロガーのドキュメントをチェックして、同時に書き込んだときにサポートされるか、壊れるかを確認する必要があります。

于 2012-10-25T19:06:10.370 に答える
0

「私の理解では、静的変数はこのアプリケーションのすべてのリクエスト間で共有されるため、ログ オブジェクトは共有されます。」 正解です。AppDomain ごとに静的メンバーのインスタンスは 1 つだけ存在します。

「しかし、メソッドDebug自体は静的ではなく、オブジェクトは静的なので、このメソッドのインスタンスは1つだけになります。それでよろしいですか?」 発言自体は正しいのですが…

要約すると、次のようになります。

  • 静的メソッドとインスタンス メソッドはどちらも、メモリ内に一度だけ「存在」します。違いは、静的メソッドは、実行するために宣言されているクラスのインスタンスを必要としないのに対し、インスタンス メソッドは必要とすることです。

  • 複数のリクエストを同時に処理できる場合は、異なるスレッドで実行する必要があります。各スレッドには独自の呼び出しスタックがあり、スレッドを使用してメソッド呼び出しを実行する場合、そのメソッドに渡された引数はそのスレッドの呼び出しスタックに置かれます。

  • これは、引数が値型 (int など) または不変型 (この場合は文字列など) である限り、別のスレッドによって変更できないことを意味します (別のスレッドからは見えないため)。 、または変更不可)。したがって、 Manager.Log() または ClientLogManager.Debug() メソッド内でメッセージが混同されることを心配する必要はありません。

したがって、現在の Manager と ClientLogManager の実装は両方ともスレッドセーフです (少なくとも、_log インスタンスがスレッドセーフである場合)。

Manager クラスで非静的メンバー変数の宣言を開始し、それらを Manager.Log() で使用するようになると、スレッドセーフではなくなります。同じ Manager インスタンスが複数のスレッドからアクセスされる可能性があります。そして、全員が同じメンバー変数に書き込みを開始すると、問題が発生します...

これで物事が少し明確になることを願っています。

于 2012-10-25T19:17:29.147 に答える