2008-08-28 2 views
39

좋아요, 제 코드에서 던져져 이상한 예외가 발생했습니다. http://msdn.microsoft.com/en-us/library/ms741547(VS.85).aspx와 난이 하나의 문제를 해결하는 방법을 모른다 :WSACancelBlockingCall 예외

System.Net.Sockets.SocketException: A blocking operation was interrupted by a call to WSACancelBlockingCall 
    at System.Net.Sockets.Socket.Accept() 
    at System.Net.Sockets.TcpListener.AcceptTcpClient() 

MSDN이에 정말 도움이되지 않습니다. 하루에 4 ~ 5 번 던져 질 뿐이지 결코 테스트 환경에서는 사용되지 않습니다. 프로덕션 사이트 및 모든 프로덕션 사이트에서만 가능합니다.

나는이 예외에 대해 묻는 게시물을 많이 발견했지만 그 원인을 파악하고 처리하거나 방지하는 방법에 대한 확실한 답은 없습니다.

코드는 별도의 백그라운드 스레드에서 실행 방법은 시작 :

public virtual void Startup() 
    { 
    TcpListener serverSocket= new TcpListener(new IPEndPoint(bindAddress, port));  
     serverSocket.Start(); 

은 그때 별도의 스레드 풀에 작업과 같은 모든 새로운 연결을 넣어 루프를 실행합니다. 이 때문에 응용 프로그램 아키텍처를 더 복잡해진다 있지만, 기본적으로 : 거기에서

while ((socket = serverSocket.AcceptTcpClient()) !=null) //Funny exception here 
    { 
     connectionHandler = new ConnectionHandler(socket, mappingStrategy); 
     pool.AddJob(connectionHandler); 
    } 
    } 

pool 별도로, 그 자체 스레드에서 각 작업 알아서 그것을 자신의 스레드를 가지고있다.

나의 이해는 AcceptTcpClient()가 블로킹 호출이고, 어떻게 든 winsock이 블로킹을 멈추고 실행을 계속하도록 말하고 있다는 것이다.하지만 왜 그런가? 그리고 내가 뭘해야되는거야? 예외를 잡아 무시하십시오.


글쎄, 나는 다른 스레드가 소켓을 닫고 있다고 생각하지만, 분명히 내 코드가 아닙니다. 내가 알고 싶은 것은이 소켓이 (소켓의 다른쪽에있는) 연결 클라이언트에 의해 닫혀 있는지 아니면 내 서버에 의해 닫혀 있는지 여부입니다. 이 순간에이 예외가 발생할 때마다 내 수신 포트가 종료되어 서비스가 종료됩니다. 원격 위치에서이 작업을 수행하면 큰 문제가됩니다.

또는 단순히 IIS 서버가 내 응용 프로그램을 종료하고 내 백그라운드 스레드와 차단 방법을 모두 취소 할 수 있습니까?

답변

35

serverSocket을 다른 스레드에서 닫을 수 있습니까? 이 예외가 발생합니다.

+0

라고 쓰십시오. 다른 스레드에서 어떻게 닫습니까? 소켓이 '휘발성'이어야합니까? –

+1

아니요, 다른 스레드가 소켓 객체에 대한 참조를 가지고 있으면 닫을 수 있습니다. – TimK

+0

차단 상태 일 경우 어떻게 동일한 스레드에서 소켓을 닫을 수 있습니까 ??? –

4

이것은 serverSocket.Stop()에서 발생할 수 있습니다. Dispose이 호출 될 때마다 내가 호출 한 여기

는 듣고 스레드 내 예외 처리 같은 모습입니다 :

try 
{ 
    //... 
} 
catch (SocketException socketEx) 
{  
    if (_disposed) 
     ar.SetAsCompleted(null, false); //exception because listener stopped (disposed), ignore exception 
    else 
     ar.SetAsCompleted(socketEx, false); 
} 

_disposed이 true로 설정 전과 지금 무슨 일이, 모든 너무 자주 예외가 발생합니다. 그래서 나를위한 해결책은 모든 스레드를 안전하게 만드는 것이 었습니다.

3

여기와 같습니다! 하지만 '서버 측'의 ReceiveBuffer가 클라이언트에서 넘쳐났다는 것을 알아 냈습니다!

(다음 TagCode이 도착할 때까지 보내는 대신 정지의 TagCode 스팸 유지 RFID-스캐너, 내 경우에는 무리) 그것은 ReceiveBuffers을 제기하고 스캐너를 다시 구성하는 데 도움이 ...

5

이 WSAcancelblablabla 피하기 위해 내 예 솔루션입니다 : 당신이 그것을 호출 한 후, 영원히 루프 플래그 그럼 먼저 스레드를 닫습니다

private void closinginvoker(string dummy) 
    { 
     if (InvokeRequired) 
     { 
      this.Invoke(new Action<string>(closinginvoker), new object[] { dummy }); 
      return; 
     } 
     t_listen.Abort(); 
     client_flag = true; 
     c_idle.Close(); 
     listener1.Stop(); 
    } 

: 는 다음과 같이 호출 방법을 사용할 수 있습니다 세계로 스레드를 정의 더 이상 기다리는 것을 차단하고 (있으면) tcpclient를 닫은 다음 리스너를 중지하십시오.