2009-08-07 5 views
0

우리는 C# .Net 서비스와 네이티브 C++ 응용 프로그램 사이의 통신에 명명 된 파이프를 사용하고 있습니다. 이 서비스는 메시지 모드 파이프를 생성 한 다음 타이머를 시작합니다.NamedPipeServerStream/async 신뢰할 수있는 연결 끊기 문제

 do 
    { 
     if (!m_bClientAttached) 
     { 
      try 
      { 
       m_pipeServer.WaitForConnection(); 
       m_bClientAttached = true; 
      } 
      catch (InvalidOperationException invope) 
      { 
       sDebug = string.Format ("Pipe wait exception InvOpEx: {0}", 
             invope.Message); 
       DebugMessage (sDebug); 
      } 
     } 

     // the message-pumping part of the loop. 

     if (m_bClientAttached) 
     { 
      try 
      { 
       if (!m_bReadInProgress) 
       { 
       m_bReadInProgress = true; 
       m_pipeServer.BeginRead (byNewRead, 0, byNewRead.GetLength (0), 
             new AsyncCallback (this.PipeReadComplete), 
             m_iReadCount); 
       } 

       if (m_OutputQueue.Count() > 0) 
       { 
       if (!m_bWriteInProgress) 
       { 
        m_bWriteInProgress = true; 
        My_Message opmsg = m_OutputQueue.ElementAt (0); 
        m_pipeServer.BeginWrite (opmsg.ToByteArray(), 0, 
              (int)(opmsg.MsgLength), 
              new AsyncCallback (this.PipeWriteComplete), 
              m_iWriteCount); 
       } 
       } 
      } 
      catch (IOException ioe) 
      { 
       sDebug = string.Format ("Main loop raised exception: {1}", 
             ioe.Message); 
       DebugMessage (sDebug); 
       DetachClientPipe(); 
      } 
      Thread.Sleep(1); 
     } 

    } while (m_bRunning); 

    m_pipeServer.Close(); 
    } 

읽기 및 쓰기 완료 루틴은 다음과 같이 :

private void PipeReadComplete (IAsyncResult iAR) 
    { 
    string sDebug; 
    int iByteCount; 
    My_Message ipmsg = new My_Message(); 
    try 
    { 
     iByteCount = m_pipeServer.EndRead (iAR); 
     if (iByteCount > 0) 
     { 
      ipmsg.FromByteArray(byNewRead); 
      m_bReadInProgress = false; 
      ... process message ... 
     } 
     else 
     { 
      try 
      { 
       DebugMessage ("PRC: Zero bytes read, disconnect pipe"); 
       DetachClientPipe(); 
      } 
      catch (InvalidOperationException invope) 
      { 
       sDebug = string.Format ("PRC - Pipe disconnect exception: {0}", 
             invope.Message); 
       DebugMessage (sDebug); 
      } 
     } 
    } 
    catch (IOException e) 
    { 
     sDebug = string.Format ("PRC: Read {0} raised exception: {1}", 
           (int)(iAR.AsyncState), 
           e.Message); 
     DebugMessage (sDebug); 
     DetachClientPipe(); 
    } 
    } 

    // ------------------------------------------------------------------ 

    private void PipeWriteComplete (IAsyncResult iAR) 
    { 
    string sDebug; 
    try 
    { 
     m_pipeServer.EndWrite (iAR); 
     lock (m_OutputQueue) 
     { 
      m_OutputQueue.RemoveAt(0); 
     } 
     m_bWriteInProgress = false; 
    } 
    catch (IOException e) 
    { 
     sDebug = string.Format ("Write {0} raised exception: {1}", 
           (int)(iAR.AsyncState), 
           e.Message); 
     DebugMessage (sDebug); 
     DetachClientPipe(); 
    } 
    } 

    // ------------------------------------------------------------------ 

    private void DetachClientPipe() 
    { 
    if (m_pipeServer.IsConnected) 
    { 
     m_pipeServer.Disconnect(); 
    } 
    m_bClientAttached = false; 
    } 

클라이언트 측 타이머 틱 루틴에서

 m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe", 
              PipeDirection.InOut, 
              1, 
              PipeTransmissionMode.Message, 
              PipeOptions.Asynchronous, 
              4096, 
              4096, 
              pipeSa); 
    m_OutputQueue = new List<My_Message>(); 

은 다음과 같습니다 주요 서비스 루프입니다 코드는 좋은 코드로 알려져 있으며 재사용됩니다. 여기에 문제가 있습니다. 클라이언트는 잘 연결할 수 있습니다. 클라이언트를 종료하면 모든 것이 정상입니다. 우리는 그것을 시작하고 다시 conect. 괜찮아요. 그럼 닫고 다시 시작하십시오. 붐 - 오류 231, 파이프 사용 중입니다. 지옥이 멈추거나 서비스가 다시 시작될 때까지 서버는 연결 시도시 파이프 사용 오류를 생성합니다. 그런 다음 두 개의 연결로 다시 돌아갑니다.

저는이 코드를 3 일 연속으로 봤습니다. 왜 이런 일을하는지 모르겠습니다. 나는 나무를 볼 수있는 나무를 볼 수없는 것 같아서, 한 쌍의 신선한 눈이나 세 개를 사용할 수 있습니다. 문제는 아무도 팀에서 C#을 많이 알지 못합니다.

업데이트

이 세 번째 연결 시도에서 실패하는 이유는 PipeReadComplete 반환 내가 0 바이트를 읽을 수 그 첫 번째 분리에 나타납니다, 그래서 파이프를 분리하고 모두가 잘. 하지만 ... 두 번째 연결 해제시 PipeReadComplete가 호출되지 않으므로 연결을 강제로 해제하지 않습니다. 기묘한.

답변

0

가능한 대답은 this related question을 참조하십시오. Suma은 동일한 문제를 경험하고 해결 한 것으로 보이지만 C#에서는 그렇지 않지만 번역하기가 쉽습니다.

+0

이미 확인했습니다. NamedPipeServerStream에 대해 알 수있는 한 동일한 호출이 없습니다. 나는 pipestream 객체를 파괴하고 다시 만드는 실험을 할 것입니다. –

+0

설명 : SetNamedPipeHandleState에 해당하는 것이 없습니다. 그가하고있는 일은 파이프를 NOWAIT로 변환하고, 새로운 연결을 기다리고 다시 WAIT으로 설정하는 것뿐입니다. 이미 새로운 연결을 기다리고 있으며 모드 변경 API가 없습니다. 결론적으로 이것은 2000 년의 IOCP wrapper API처럼 실제 쓰레기 시나리오를 다루지 않는 MS의 쓰레드 풀 API의 또 다른 사례이다. 나는 실을 수작업으로 태워야 할 것 같아요. –

1

Bob : 빠른 수정을 위해 궁금한 점이 있습니까? 서버 인스턴스 매개 변수를 1 이상으로 설정해 보았습니까? 2 회 시도한 후에도 계속 실패하는지 확인 했습니까? 1 대신에 10을 넣고 도움이되는지 확인하십시오. 또한 관리되지 않는 코드를 게시하는 경우에도 도움이됩니다. 현재 Windows 서비스 플러스 관리되지 않는 dll IPC와 동일한 작업을 수행하고 있습니다.

m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe",  
             PipeDirection.InOut,    
             10, 
             PipeTransmissionMode.Message, 
             PipeOptions.Asynchronous,             
             4096, 
             4096, 
             pipeSa);  

실제로는 항상 서버 파이프 인스턴스가 하나만 있어야합니다.

관련 문제