2009-07-17 16 views
0

私は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"); 
+0

Send(string)メソッドで正しく割り当てられていることを確認してください。あなたはtgeコードを単純化するときに何か言及することを忘れましたか? –

+1

なぜこれは静的なクラスですか? – devio

+0

Devio-多分それはあってはならない、私はまだ学んでいる。最も洗練されたソリューションのように見え、オブジェクトを作成する必要はありませんでした。クラス名はそれほど良くなく、変更する必要があります - MessageHandlerはおそらくそれらを転送してからです。 MessageHandler.Send(Message)。 – Kildareflare

答えて

4

スレッドが現在同じメソッドの途中にある間に他のスレッドがSend(文字列)を呼び出す可能性があるので、このコードのスレッド「unsafetyness」が問題になる可能性があります。私は、メッセージクラスの次の書き直しをお勧めします:

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 
    } 
} 
+0

ピーター - これは問題を修正したようです。それが起こるにつれ、私は最近、メンバーの方々を直接使っていました。もちろん、この例ではコース用の馬 - 馬を渡す方が合理的なようです。 – Kildareflare

+0

通常、メンバ変数は大丈夫ですが、スレッドの安全性に関しては静的メンバ変数に特別な注意が必要です。うれしいことに問題を解決しました。 –

2

これは、

Message.Send(""); 

やあなたのAppDomainがアンロードされているを呼び出す別のスレッドに最も可能性が高いです。それ以上の情報がなければ、確かに言うことは難しいです。

0

1つのフィールドが同じ値を保持し、もう1つのフィールドがそうでない場合、私は非常に驚くでしょう。

これはWebアプリケーションの場合、アプリケーションがリサイクルされている場合に発生します。

2

あなたはいくつかの巨大なスレッドの安全上の問題があります。これは、今のように静的な働き

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

が、スレッドごとのです:あなたは本当にこの静的をしたい場合は、そこに生意気な修正です。危機が回避された。しかし、これはちょっと...まあ、私は、自分自身の必要性を避けようとしますが、うまくいくでしょう。

重要:イニシャライザはスレッドごとであり、要求ごとではありません。スレッドが再利用される可能性が高いので、使用する前に状態を初期化するか、古いゴミを持つ可能性があります。

+0

これは一度に1つのスレッドでのみ呼び出されますが、ヒントのおかげで!私は初期化メソッドを持っていましたが、コードを減らすためにそれを削除しました。 – Kildareflare

0

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

単体テストまたはMessage.Send( "Hello World")を呼び出す単純なテストハーネスを記述します。出力をアサートします。これを呼び出し元のコードベースから分離すると、異常に動作しているMessageクラスであるか、悪い/予期しないデータを送信しているコンシューマであるかがわかります。

また、残りの機能がブールをリセットしない限り、最初のメッセージが送信された後は常にtrueになります。

+0

それははいのように起こるので、ブールはリセットされます - 他にも多くのフォーメーションとロジックがあります。私は問題を抱えていた問題に焦点を当てるように、コードを単純化しました。私は将来的にこれを強調するためのコメントを追加するつもりだと思う。 – Kildareflare

+0

わかりました。私はちょうどそれがリセットされていないという機会を逸して追加しました。しばらくして、ぶら下がっている果物が実際に動き出します。 –

関連する問題