2011-01-12 10 views
0

Ich habe dieses kleine TCP/IP-Programm und für das Leben von mir kann ich dieses Problem nicht herausfinden (Ich überprüfte Google). Wenn ich einen Puffer im Callback-Delegaten von BeginReceive lese, setze ich einige globale Variablen auf 0, aber wenn die Funktion startet, gibt es Daten in den Variablen. Ich habe zwei globale Variablen in der Klasse:TCP/IP, globale Variablen initialisieren in asynchronen Aufruf

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; 
} 

Am Ende der Funktion, wo ich:

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

GetMessageLength(newMessage) liefert ein 0 und StripNumber(newMessage) einen leeren String zurück, aber das nächste Mal, wenn ich anrufen die Funktion, zu Beginn der Funktion, bevor irgendetwas verarbeitet wird, MessageLength = 30 und eine Nachricht hat Daten von vorher. Keine andere Stelle im Programm, um diese Variablen zu referenzieren, d. H. Ich greife nicht auf die Variablen außerhalb der obigen Funktion zu, und beide Variablen sind global.

Antwort

1

Ich stelle mir vor, was passiert hier ist, dass Sie gleichzeitige Anrufe haben, die gleichzeitig an den Daten arbeiten, daher die Ergebnisse.

Hier gibt es zwei Lösungen. Der erste wäre, Sperren um den Abschnitt zu platzieren, der Ihre statischen (nicht "globalen") Variablen im obigen Code berührt.

Die zweite wäre, den Zugriff auf die statischen Variablen zu kapseln (Sie machen nicht völlig klar, welche Variablen betroffen sind) und in dieser Kapselung, den Zugriff synchronisieren (mit lock/Monitor oder einem anderen Mechanismus).

Verwenden Sie dann im obigen Code lokale Variablen, kopieren Sie die Werte der statischen Variablen lokal, führen Sie Ihre Arbeit aus und weisen Sie sie dann zurück.

Sie würden die erste Lösung verwenden, wenn Sie sicherstellen müssen, dass der obige Code seriell ausgeführt wird, mit anderen Worten, Sie müssen sicherstellen, dass das Lesen, die Änderung und das Schreiben alle in der Reihenfolge auftreten.

Die zweite wäre, wenn Sie einen Leisten-in-Wins-Ansatz haben.

+0

Ja, ich bin neu im Threading :) Lassen Sie mich Ihnen eine Anfängerfrage stellen, vor allem sind die Variablen nicht statisch, sie sind nur in der Klasse definiert und nicht lokal in der Funktion definiert. Wenn ich sequentiellen Zugriff möchte und gehe nach dem ersten Vorschlag und ich Sperren um die Variablen, die ich ändern möchte, was passiert, wenn der erste Thread ändert den Wert und verlässt die Sperre und dann der zweite Thread ändert es vor dem ersten Thread beendet das Senden die Nachricht und setzt ammessage und MessageLength auf 0. Ich habe versucht, eine Sperre um die gesamte Funktion, aber es hat nicht funktioniert. Danke für die Hilfe. – Eitan

+0

@Eitan: Nun, Sie können es nicht um die gesamte Funktion, Sie würden es in der asynchronen Methode, die aufgerufen wird, sowie den Block des Codes zugreifen Sie auf die Methoden im Code, der die asynchrone Methode aufruft . – casperOne