2013-10-31 1 views
0

내장 시스템 인터페이스의 경우 직렬 포트를 읽는 데 최대 8 개의 읽기 모드 (아래 코드로 두 개만 표시 - FREERUN 및 BLOCKRUN)를 구현합니다. .boost :: asio가 직렬 포트에 대한 잘못된 처리기를 호출합니다.

void CSerialBoost::ReaderTest() 
{ 
while (RUNflag) 
    switch (RUNstate) { 

    case FREERUN: 
      port.async_read_some(asio::buffer(TextIn, SZTXT), 
       boost::bind(&CSerialBoost::OnReadFree, this, asio::placeholders::error, asio::placeholders::bytes_transferred)); 

      server.reset(); 
      server.run(error);  // it calls OnReadBlock() here 
      break; 

    case BLOCKRUN: 
      port.async_read_some(asio::buffer(TextIn, SZTXT), 
       boost::bind(&CSerialBoost::OnReadBlock, this, asio::placeholders::error, asio::placeholders::bytes_transferred)); 

      server.reset(); 
      server.run(error);  // it calls OnReadFree() here 
      break; 

    default: break; 
    } 

    port.cancel(error); // cancel all IO operations 
} 

클래스 CSerialBoost은 다음과 같은 멤버를 가지고 :이 독자의 단순화 ReaderTest() 함수처럼 보인다 내가 다른 하나 개의 모드로 전환 할 때 예기치 않은 동작이

asio::io_service server; 
asio::serial_port port; 
asio::error_code error; 

volatile int RUNstate; // reader mode 
volatile int RUNflag; // start/stop flag 

. 가 들어오는 데이터없고 코드는 다른 스레드에서에서 blockrun로 전환하기 위해, FREERUN에서 실행 가정 I이 수행 예상대로

RUNstate = BLOCKRUN; 
server.stop();  // unblock the event loop 

동작은에서 blockrun로 전환하고, 서버에 도달 할 때 .run (error) 줄 BLOCKRUN 경우 오류가 operation_aborted CSerialBoost :: OnReadFree() 함수를 호출합니다. FREERUN으로 다시 전환 할 때도 마찬가지입니다. FREERUN의 경우 server.run (오류)에 도달하면 CSerialBoost :: OnReadBlock()을 호출합니다.

이것은 항상 다른 모드의 함수를 호출하기 때문에 오도 된 것입니다. 내가 IO 서비스를 중지/취소 할 때 나는 각 경우가 자신의 기능을 호출 할 것이라고 기대한다. 너무 많이 기대합니까? 아니면 정상적으로 작동합니까? 내가 뭔가 잘못하고 있는거야? 이 문제를 해결하는 방법에 대한 힌트를 제공해주십시오. (승부 : asio 1-5-3, Win XP 및 Win 7, Visual Studio 2010에서는 새로운 기능을 제공합니다.)

감사합니다. MA.

답변

0

이것은 예상되는 동작입니다.

io_service::stop()io_service::reset()io_service의 이벤트 루프 상태 만 제어합니다. 지연 실행 (준비 실행) 또는 사용자 정의 핸들러 오브젝트에 대해 스케줄 된 핸들러의 수명에는 영향을주지 않습니다.

server.run()이 호출 될 때 async_read_some 작업은 io_service에 대기합니다. 이벤트 루프가 server.stop()을 통해 명시 적으로 중지 된 경우 작업의 완료 핸들러가 아직 호출되지 않은 경우 작업 또는 완료 핸들러가 io_service에 대기합니다. while 루프에서 실행을 계속합니다. 여기서 port.cancel()port에서 걸출한 작업을 취소하고 완료 핸들러를 boost::asio::error::operation_aborted의 실행 코드로 설정합니다. 따라서 다음 번에 server.run()이 호출 될 때, 취소 된 작업을 위해 실행할 준비가 된 처리기가 실행됩니다. io_service에 완료를 실행

  • : 고려 중

    . 이 경우 종종 상태 설정, 처리되지 않은 작업 취소 및 완료 처리기가 io_service에 추가 작업을 게시하지 못하게해야합니다. Boost.Asio는 공식 timeout 예제를 제공하고 완료시 io_service까지 실행되는 시간 초과 접근 방식은 here으로 표시됩니다.

  • 비동기식 호출 체인에 상태 시스템이 구현되어 있어야합니다. 이렇게하면 stop(), reset()io_service이 다시 run()이 될 필요가 없습니다.
  • io_service 개체의 수명을 제어하는 ​​경우 을 io_service으로 지정하면 처리되지 않은 모든 처리기가 파괴됩니다. 한 가지 방법은 this 대답에서 찾을 수 있습니다.
+0

감사합니다. 귀하의 대답은 "문제"를 분명히합니다. 내가 언급 한 첫 번째 솔루션을 구현하는 데 관심이있다. (내 코드에는 10 초의 타임 아웃 타이머가 있지만 때로는 server.stop()이 호출되기 전에 시간이 다 떨어진다.) io_service 내부 동작에 대해 더 많은 것을 읽을 수있는 인터넷 리소스가 있으며,이를 실행하여 추가 작업을 게시하는 작업을 방지하는 방법에 대해 알고 있습니까? 이 주제에 대한 asio 문서는 매우 짧습니다. –

+0

@ManuelaArcuri : [Boost.Asio] (http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio.html) 개요, 참조 및 예제가 상당히 완벽하다는 것을 알았습니다. 그 주위를 탐색하는 것은 까다로울 수 있지만 정보는 종종 있습니다. 링크에서 답변되지 않은 특정 질문이 있으십니까? –

관련 문제