2011-01-12 35 views
0

私はこの小さなtcp/ipプログラムを持っています。私の人生のために私はこの問題を解決することはできません。私がBeginReceiveのコールバックデリゲートのバッファを読み込んでいるときに、いくつかのグローバル変数を0に設定しますが、関数が開始するときに変数にデータがあります。私のクラスの2つのグローバル変数があります。私が持っている機能の終わりでTCP/IP、非同期呼び出しで初期化するグローバル変数

string content; 
var buffer = ((byte[]) ar.AsyncState); 
int len = MySocket.EndReceive(ar); 
if (len > 0) 
{ 
    string cleanMessage; 
    content = Encoding.ASCII.GetString(buffer, 0, len); 
    if (MessageLength == 0) 
    { 
     MessageLength = GetMessageLength(content); 
     cleanMessage = StripNumber(content); 
    } 
    else 
     cleanMessage = content; 

    if(cleanMessage.Length <1) 
    { 
     if(MySocket.Connected) 
      MySocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, 
       new AsyncCallback(Read), buffer); 
     return; 
    } 
    if(MessageLength > cleanMessage.Length) 
    { 
     MessageLength = MessageLength - cleanMessage.Length; 
     amessage += cleanMessage; 
    } 
    else 
    { 
     amessage += cleanMessage.Substring(0, MessageLength); 
     if (OnRead != null) 
     { 
      var e = new CommandEventArgs(this, amessage); 
      Control target = null; 
      if (OnRead.Target is Control) 
       target = (Control)OnRead.Target; 
      if (target != null && target.InvokeRequired) 
       target.Invoke(OnRead, this, e); 
      else 
       OnRead(this, e); 
     } 

     string newMessage = cleanMessage.Substring(MessageLength); 
     MessageLength = GetMessageLength(newMessage); 
     amessage = StripNumber(newMessage); 
    } 
    MySocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, 
     new AsyncCallback(Read), buffer); 
    return; 
} 

string newMessage = cleanMessage.Substring(MessageLength); 
MessageLength = GetMessageLength(newMessage); 
amessage = StripNumber(newMessage); 

GetMessageLength(newMessage)を0を返すとStripNumber(newMessage)戻り空の文字列が、私は呼んで次回関数が何か処理される前の関数の冒頭に、MessageLength = 30であり、メッセージには以前からのデータがあります。これらの変数を参照するプログラム内の他の場所はありません。つまり、上記の関数の外の変数にはアクセスしていません。両方の変数はグローバルです。

答えて

1

私は、ここで起こっていることは、同時にデータを処理している同時呼び出しがあり、その結果であることを想像しています。

これには2つの解決策があります。最初は、上のコードで静的(グローバルではない)変数に触れるセクションの周りにロックを置くことです。

2番目は静的変数(どの変数がbtwに影響を与えているかを完全にはっきりさせていない)とそのカプセル化、アクセスの同期化(lock/Monitorまたは他のメカニズムを使用した)へのアクセスをカプセル化することです。

次に、上記のコードでローカル変数を使用し、静的変数からローカルに値をコピーし、作業を実行してから、それらを割り当てます。

上記のコードが連続して実行されることを確認する必要がある場合、つまり、読み込み、変更、および書き込みがすべて順番に行われることを確認する必要がある場合は、最初のソリューションを使用します。

2番目の方法は、ラスト・イン・ウィンのアプローチがある場合です。

+0

ええ私はスレッディングに慣れていません:)初心者の質問をしましょう。最初に、変数は静的ではなく、クラス内で定義されており、関数内ではローカルに定義されていません。私がシーケンシャルアクセスを望んでいて、最初の提案に従い、私が変更したい変数の周りにロックを置くと、最初のスレッドが値を変更してロックを終了し、メッセージとamessageとMessageLengthを0に設定します。私は関数全体をロックしようとしましたが、うまくいきませんでした。助けてくれてありがとう。 – Eitan

+0

@Eitan:関数全体に渡すことはできません。呼び出されるasyncメソッドと、asyncメソッドを呼び出すコードのメソッドにアクセスするコードブロック。 – casperOne

関連する問題