2011-01-12 4 views
0

나는이 작은 tcp/ip 프로그램을 가지고 있으며, 나는이 문제를 해결할 수 없다 (나는 구글을 체크했다). BeginReceive의 콜백 대리자에서 버퍼를 읽을 때 일부 전역 변수를 0으로 설정하지만 함수가 시작될 때 변수에 데이터가 있습니다. 내가 가지고있는 함수의 끝에서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

나는 여기서 일어나는 일이 동시에 데이터에서 작업하는 동시 호출을 가지고 있다는 것을 상상한다.

두 가지 해결책이 있습니다. 첫 번째는 위의 코드에서 정적 ("전역"이 아닌) 변수에 닿는 부분 주위에 자물쇠를 배치하는 것입니다.

두 번째는 정적 변수에 대한 액세스를 캡슐화하고 (어떤 변수가 btw에 영향을 미치는지 완벽하게 알지 못함) 해당 캡슐화, 잠금/모니터 또는 다른 메커니즘을 사용하여 액세스를 동기화하는 것입니다.

그런 다음 위의 코드에서 로컬 변수를 사용하고 정적 변수의 값을 로컬로 복사하고 작업을 수행 한 다음 다시 할당합니다.

위의 코드가 순차적으로 실행되는지, 즉 읽기, 수정 및 쓰기가 모두 순서대로 수행되는지 확인해야 할 때 첫 번째 솔루션을 사용할 수 있습니다.

두 번째 방법은 최후 승 방식입니다.

+0

그래, 처음부터 스레딩에 빠졌어 :) 초급 질문을하자. 먼저 변수가 정적이 아니고 클래스에 정의되어 있고 함수 내에서 로컬로 정의되지 않았다. 순차 액세스를 원한다면 첫 번째 제안에 따라 이동하고 변경하려는 변수 주위에 잠금을 설정합니다. 첫 번째 스레드가 값을 변경하고 잠금을 종료 한 다음 두 번째 스레드가 첫 번째 스레드가 전송을 완료하기 전에 변경하면 어떻게됩니까? 메시지 및 amessage 및 MessageLength 0으로 설정합니다. 전체 함수 주위에 잠금을 가려고했지만 작동하지 않았다. 도와 주셔서 감사합니다. – Eitan

+0

@Eitan : 글쎄, 전체 함수에 넣을 수는 없다. 호출되는 async 메서드와 async 메서드를 호출하는 코드의 메서드에 액세스하는 코드 블록에 배치하면된다. . – casperOne