2013-02-13 4 views
4

서비스 버스를 사용하여 웹 역할과 작업자 역할을 연결하고 있습니다. 내 작업자 역할이 연속 루프에 있고 QueueClient.Receive() 메소드로 웹 역할에서 보낸 메시지를 수신하고 있습니다.QueueClient.Receive()에 대한 비동기 메서드?

그러나이 방법을 사용하면 서비스 버스 대기열에 메시지가 없으면 추가 실행을 위해 다음 줄로 이동하지 않고 메시지 수신에 몇 초 기다립니다. 나는 메시지를 받기위한 비동기적인 방법이 있기를 바랬다. 또는이 대기 시간을 설정하기위한 적어도 어떤 방법?

이 BeginReceive 메서드는 QueueClient의 msdn 설명서에서 발견되었으며이 질문에 대한 답변이 될 것이라고 기대했지만이 방법을 사용하는 방법을 모릅니다. 메서드 매개 변수는 비동기 콜백 및 개체 상태입니다.

아이디어가 있으십니까?

업데이트 : Sandrino의 훌륭한 솔루션 덕분에 비동기 적으로 작동합니다. 그러나 비동기가되어 이제는 나에게 몇 가지 문제가 생겼다. 내 VS가 충돌하고있어. 문제가 무엇인지 잘 모릅니다. 아래 코드가 사용하고 있습니다.

작업자 역할 :

public override void Run() 
    { 
while (!IsStopped) 
     {     
       // Receive the message from Web Role to upload the broadcast to queue 
       BroadcastClient.BeginReceive(OnWebRoleMessageReceived, null);      

       // Receive the message from SignalR BroadcastHub 
       SignalRClient.BeginReceive(OnSignalRMessageReceived, null);      

      } 
} 


public void OnWebRoleMessageReceived(IAsyncResult iar) 
    { 
     BrokeredMessage receivedBroadcastMessage = null; 
     receivedBroadcastMessage = BroadcastClient.EndReceive(iar); 

     if (receivedBroadcastMessage != null) 
     { //process message 
      receivedBroadcastMessage.Complete(); 
     } 
    } 

public void OnSignalRMessageReceived(IAsyncResult iar) 
    { 
     BrokeredMessage receivedSignalRMessage = null; 
     receivedSignalRMessage = SignalRClient.EndReceive(iar); 

     if (receivedSignalRMessage != null) 
     { 
      //process message 
      receivedSignalRMessage.Complete(); 

      WorkerRoleClient.Send(signalRMessage); 
     } 
    } 

오전 내가 작업과 충돌을 통해 VS를 만드는 것도 놓치고? 왜냐하면 BeginReceive로 옮기기 전에, QueueClient.Receive를 사용할 때 잘 작동하고 충돌하지 않기 때문입니다.

감사

답변

6

BeginReceive 방법은 귀하의 경우 길을 가야하는 것입니다. 당신은 일반적으로 다음과 같이 호출합니다 :

void SomeMethod() 
{ 
    ... 
    client.BeginReceive(TimeSpan.FromMinutes(5), OnMessageReceived, null); 
    ... 
} 

void OnMessageReceived(IAsyncResult iar) 
{ 
    var msg = client.EndReceive(iar); 
    if (msg != null) 
    { 
     var body = msg.GetBody<MyMessageType>(); 
     ... 
    } 
} 
+0

감사합니다! 그것은 비동기 적으로 작동하지만 왜 서비스 버스에 메시지를 보냈을 때 내 VS가 매달려서 쓰러졌다. 질문을 업데이트하고 코드를 추가하여 문제가 무엇인지 알면 알려주십시오. Thanks again again – Bitsian

+0

BeginReceive 메서드가 즉시 반환됩니다. 즉, while 루프가 반복적으로 반복됩니다 (무한 루프). 이 같은 while 루프는 동기식 메서드와 잘 동작하지만 비동기 호출을 사용할 때는 그렇지 않습니다. –

+0

while 루프에 조건문을 추가하여 문제를 해결했습니다. – Bitsian

1

이 내가했던 방법 (확장 Sandrino 데 마티아의 솔루션)입니다 :

void SomeMethod() 
{ 
    ... 
    client.BeginReceive(TimeSpan.FromSeconds(5), OnMessageReceived, null); 
    ... 
} 

void OnMessageReceived(IAsyncResult iar) 
{ 
    if(!IsStopped) 
    { 
     var msg = client.EndReceive(iar); 
     if (msg != null) 
     { 
      var body = msg.GetBody<MyMessageType>(); 

      ... //Do something interesting with the message 

      //Remove the message from the queue 
      msg.Complete(); 

      client.BeginReceive(TimeSpan.FromSeconds(5), OnMessageReceived, null); 
     } 
    } 
} 

나는 정지 메커니즘에 "무한 루프"가 그런 식으로 .

1

애저 ServiceBus SDK (download link)의 최신 버전은 비동기 적으로 메시지를 수신 할 완벽하게 지원합니다 :

async Task TestMethod() 
{ 
    string connectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString"); 

    QueueClient Client = QueueClient.CreateFromConnectionString(connectionString, "TestQueue"); 
    var message = await Client.ReceiveAsync(); 
} 
+0

동기식 Receive()를 사용하는 이유가 확실하지 않습니다.)'(https://azure.microsoft.com/en-us/documentation/articles/service-bus-brokered-tutorial-dotnet/)에서 시작하십시오. 'ReceiveAsync'를 기다리도록 변경하려고 시도했을 때 메시지를받지 못했습니다! – orad

+0

Nevermind, 메인 메소드에서'Task.WaitAll (Queue());'를 사용했는데 성공했습니다! – orad

+0

자습서가 최신 버전이 아닙니다. 어쨌든 비동기를 사용하는 것이 항상 좋은 것은 아닙니다. 필요한 경우 비동기 만 사용하십시오. 코드에 어떤 문제가 있습니까? – Thomas