2014-07-09 4 views
2

나는이 상황에 있습니다 : 많은 클라이언트가 컨트롤러에 명령을 보낼 수 있으며 컨트롤러는 각 명령을 순서대로 처리하고 각 클라이언트에 응답을 되돌려 보내야합니다. 클라이언트는 응답을 비동기 적으로 "대기"합니다.스레드와 작업 간의 통신 대기

지금까지 클라이언트에서 명령을 받으면 ConcurrentQueue에 명령을 대기시키고 클라이언트가 응답을 비동기 적으로 기다리는 작업을 실행합니다. 콘트롤러는 ConcurrentQueue에서 항상 새로운 명령을 검색하고, 먼저 처리하고, 처리하고 클라이언트 (클라이언트)에게 응답해야하는 Thread를 가지고 있습니다. 그러나 여기에 내가 어떻게 멈출 지 모르겠다. 컨트롤러는 명령을 보낸 클라이언트에 정확히 응답합니다 (컨트롤러에는 많은 명령이있는 대기열이 있지만 누가 그 명령을 보냈는지 알지 못합니다).

내 생각 : 스레드에서 응답 개체가있는 작업으로 직접 메시지를 보내는 것이 좋을 것입니다. 가능한가?

내 코드 :

private ConcurrentQueue<byte[]> sendBuffer; 

public async Task<IViewAppMessage> sendCommandAsync(byte[] command) 
{        
    sendBuffer.Enqueue(command); 

     return await Task.Run<IViewAppMessage>(() => 
     { 
      //Pool for a response 
     }   
} 

/* Method executed within a Timer worker thread */ 
private void senderPool(object stateInfo) 
{ 
    try 
    { 
     //Stop timer 
     senderTimer.Change(Timeout.Infinite, Timeout.Infinite); 
     //Take command from FIFO 
     byte[] commandToSend; 
     if(sendBuffer.TryDequeue(out commandToSend)) 
     { 
      //Send command to camera 
      cameraSender.Send(commandToSend, commandToSend.Length);      
      byte[] response = cameraListener.Receive(ref endPoint); 

      IViewAppMessage returnMessage = processResponse(response); 

      //Notify the response. HOW????????????? 
     }     
    } 
    catch 
    { 
     //Notify Error 
    } 
    //In any case, timer restarts 
    finally 
    { 
     try 
     { 
      //Arrancamos timer 
      senderTimer.Change(100, Timeout.Infinite); 
     } 
     catch 
     { 
      //Fatal error 
     } 
    } 
} 

감사합니다!

편집 : 나는 모든 reponses와 BlockingCollection을 사용할 수 있습니다 알고, 그래서 보낸 사람이 응답을받을 때, 그것은하지만 함께 컬렉션에 그것을 할당하고 응답을 한 후 고객의 여론 조사

그 접근 방식 나는 ID와 함께 응답을 확인하는 ID (또는 비슷한) 각 클라이언트를 제공해야합니다. 그 해결책이 될 수도 있지만 직접 응답을 사용하여 작업에 메시지를 보내는 것이 가능한지 궁금합니다. 클라이언트가 설문 조사를하거나 설득하는 것이 필요하지 않기 때문에 비슷한 점이 더 나은 접근 방식이라고 생각하기 때문입니다. 동시 ID가 아닙니다.

+0

어떤 유형의 클라이언트 ?? –

+0

모든 클라이언트. 그것은 라이브러리이므로 Windows Form에서 참조 할 수 있으며 클라이언트는 ÜI 또는 WCF 서버가되며 클라이언트는 서비스 엔드 포인트가됩니다. – MorgoZ

+0

명령을 대기열에 추가 할 때이를 감쌀 수 있습니까? 보낸 사람의 세부 정보를 저장하는 일부 개체에서? –

답변

1

전송할 항목을 대기열에 추가하는 작업 만 수행하면 안됩니다. 소비자가 제작자에게 알릴 수있는 데이터를 포함시킵니다. 예를 들어 적절한 시점에 소비자가 완료하도록 설정 한 TaskCompletionSource을 포함 할 수 있습니다. 생산자는 await TaskCompletionSource.Task 일 수 있습니다.

1

대기열 - 클래식 생산자 소비자 패턴 대신 BlockingCollection을 사용할 수 있습니다. example in MSDN documentation을 확인하십시오. queue.Take()은 항목이 대기열에서 사용 가능할 때까지 차단되므로 타이머를 사용할 필요가 없습니다.

+0

그 방법에 대해 자세히 설명해 주시겠습니까? AFAIK'BlockingCollection'은 기본적으로'ConcurrentQueue'를 래핑합니다. –

+0

@DanielKelley bc.Take()는 항목이 다른 스레드에서 추가 될 때까지 차단합니다. – ziya

+0

그래도 클라이언트에게 응답을 보내는 데 도움이 될지 모르겠습니다. SendQueue 및 ResponseQueue를 사용 하시겠습니까? 나는 @DanielKelley에 말했듯이, 직접 메시징 솔루션이 있는지 알고 싶습니다. ResponseQueue에서 ID를 사용하여 응답하기 위해 모든 클라이언트를 풀링하는 것보다 낫습니다. – MorgoZ