2009-11-17 6 views
1

:스레딩 및 소켓 나는 다음과 같은 한

ThreadStart startThread = 
    delegate 
    { 
      mySocket.StartListen(); 
    }; 

mySocket 지금)을 (듣기에 반복 될 때 I : 여기

new Thread(startThread).Start(); 

가 StartListen입니다 :

public void StartListen() 
{ 
Object locker = new Object(); 

// Lock resources 
lock (locker) 
{ 
    S = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, 
     System.Net.Sockets.SocketType.Stream, 
     System.Net.Sockets.ProtocolType.Tcp); 
    S.Blocking = false; 

    try 
    { 
    S.Bind(serverEP); 
    S.Listen(1000); 
    isListening = true; 

    /* 
    * While statement not required here because AcceptConnection() 
    * method instructs the socket to BeginAccept() again... 
    */ 
    //while (true) 
    //{ 
    connectDone.Reset(); 
    S.BeginAccept(new AsyncCallback(AcceptConnection), Channel); 
    connectDone.WaitOne(); 
    //} 
    } 
    catch (System.Net.Sockets.SocketException SockEx) 
    { 
    Console.WriteLine("*****[" + name + "] " + SockEx.SocketErrorCode + ":"); 
    Console.WriteLine("*****[" + name + "] " + SockEx.Message); 
    } 
} 
} 

의 때문에 비동기 메서드는 실제로 '끝내지'않고 계속 진행할 다른 신호를 반환합니다. 위의 Thread.Start() 이후에 구현 한 명령은 제대로 작동하지 않습니다. 예를 들어 StartListen에서 isListening = true이 있음에 유의하십시오. 스레드를 시작한 후 IsListening 속성을 사용하려고합니다. 항상 false로 리턴됩니다.

스레드를 어떻게 시작해야합니까? 비동기 메서드 (ThreadStart.BeginInvoke())를 더 선호 할 수 있습니까? ManualResetEvent를 사용하는 것과 비슷하지 않습니까?

답변

2

isListeningvolatile으로 지정하십시오. 내가 아는 한, 당신은 두 개의 다른 쓰레드에서이 플래그를 참조하고 있습니다. 일반적으로 스레드간에 공유되는 데이터는 동기화되어야하지만 그렇게하고있는 것처럼 보이지는 않습니다. 그러나 플래그가 bool 유형 인 경우, .NET 프레임 워크가 bool 유형의 읽기 및 쓰기가 원자 적이라는 것을 보장하기 때문에 기술적으로 액세스를 동기화 할 필요가 없습니다. (생각하면 올바르게 말합니다. 누군가 기술적으로 올바른 것이 아니라면 그것을 바로 잡으십시오.) 그러나 해당 유형의 읽기가 실제로 가장 최근 값을 가져 오려면 volatile으로 표시해야합니다.

또한 Socket 클래스로이 작업을 시도하는 대신 TcpListener 클래스를 사용하는 것이 좋습니다. 당신이하고있는 일은 잘못이 아니지만, TcpListener 클래스는 코드를 읽고 관리하기가 더 쉽습니다.

마지막으로 사용중인 locker 객체는 StartListen() 메소드의 로컬이므로 실제로 아무 것도 수행하지 않습니다. 동기화 개체가 효과를 내기 위해서는 공유 데이터에 대한 직렬화 된 액세스가 필요한 스레드에 액세스 할 수 있어야합니다. 당신이 여기에서하는 것처럼 다른 스레드는 locker 변수에 접근 할 수 없으므로 쓸모 없게 만듭니다.

+0

이전에 '휘발성'을 사용하지 않았습니다. 나는 그것에 대해 읽을 것이다. TcpListener를 사용하는 것은 완전히 의문의 여지가 없습니다. 그러나 모든 비동기 작업은 이미 Socket 클래스로 작성하고 작업하고 있습니다. TcpListener/TcpClient에서 쉬운 방법을 사용하는 대신 기본 클래스로 작업하기로했습니다. :) – IAbstract

+0

'Socket' 클래스를 사용하는 것은 잘못이 아닙니다. 그것은'TcpListener'가'Socket'을 어떻게 사용하는지 명시 적으로 설계 되었기 때문에 훨씬 쉽습니다. –

관련 문제