0

OK 文字列とブール値の 2 つの静的メンバーを持つ静的クラスがあります。
public static メソッドは、渡されたパラメーターの状態に基づいて、これらのメンバーに値を割り当てます。

次に、静的メンバーを処理するプライベート静的メソッドが呼び出されます。

問題は、ブール値がパブリック関数で設定された値を保持する一方で、文字列は保持されないことです。デフォルトで初期化された値に戻ります。どうしてこれなの?
簡略化したコードを以下に示します。

static class MessageHandler
{
    private static String m_messageToSend = String.Empty;
    private static bool m_requiresACK = false;


    public static void Send(String message)
    {
         //formatting etc (actual method sets more fields)
         m_messageToSend = message;
         m_requiresACK = true;

         Send();
    }

    private void static Send()
    {
        SendMessageDelegate sendDelegate = DoSend;
        //At this point m_requiresACK remains true but m_messageToSend does not 
        //hold value of message; it is empty.
        IAsyncResult ar = sendDelegate.BeginInvoke(m_messageToSend, m_requiresACK);


        //rest of function
    }
}

//some other class
MessageHandler.Send("Hello");
4

5 に答える 5

4

スレッドが現在同じメソッドの途中にあるときに他のスレッドがSend(string)を呼び出す可能性があるため、このコードのスレッドの「安全性が低い」ことが問題になる可能性があります。Messageクラスを次のように書き直すことをお勧めします。

static class Message
{
    public static void Send(String message)
    {
         Send(message, true);
    }

    private void static Send(string messageToSend, bool requiresACK)
    {
        SendMessageDelegate sendDelegate = DoSend;
        IAsyncResult ar = sendDelegate.BeginInvoke(messageToSend, requiresACK);

        //rest of function
    }
}
于 2009-07-17T12:30:54.997 に答える
2

これは、別のスレッドが呼び出していることが原因である可能性があります

Message.Send("");

または、AppDomainがアンロードされています。より多くの情報がなければ、確かに言うのは難しいです。

于 2009-07-17T12:26:41.050 に答える
2

そこにはいくつかの大きなスレッドセーフの問題があります。本当にこの静的が必要な場合は、生意気な修正があります。

[ThreadStatic]
private static String m_messageToSend = String.Empty;
[ThreadStatic]
private static bool m_requiresACK = false;

これは静的として機能するようになりましたが、スレッドごとです。危機は回避されました。しかし、これは少し... まあ、私は自分で必要を避けようとしますが、うまくいきます。

重要:初期化子はリクエストごとではなく、スレッドごとです。スレッドが再利用される可能性が高いため、スレッドを使用する前に必ず状態を初期化する必要があります。そうしないと、古いガベージが発生する可能性があります。

于 2009-07-17T12:44:16.717 に答える
0

一方のフィールドが同じ値を保持し、もう一方のフィールドが保持しない場合、私は非常に驚きます。

これがWebアプリケーションの場合、アプリケーションがリサイクルされると発生する可能性があります。

于 2009-07-17T12:28:45.013 に答える
0

あなたのコメントで、その最初の行の後、パラメーターの値を保持する代わりに、プライベート変数が空になっていることがわかります。Send() の最初の行に到達するとすぐに、これは本当ですか?

Message.Send("Hello World"); を呼び出す単体テストまたは単純なテスト ハーネスを記述します。出力に対してアサートを行います。これを呼び出し元のコードベースから分離することで、異常な動作をしているのが Message クラスなのか、それとも不良/予期しないデータを送信している消費者なのかを明らかにすることができます。

また、関数の //rest に bool のリセットが含まれていない限り、最初のメッセージが送信された後は常に true になります。

于 2009-07-17T12:58:12.510 に答える