2013-02-13 3 views
4

J'utilise le bus de service pour connecter le rôle Web et le rôle de travailleur. Mon rôle de travail est dans une boucle continue et je reçois le message envoyé par le rôle web avec la méthode QueueClient.Receive(). Mais avec cette méthode, s'il n'y a pas de message sur la file d'attente du bus de service, il attend quelques secondes pour recevoir le message plutôt que de passer à la ligne suivante pour une exécution ultérieure. J'espérais qu'il y aurait une méthode asynchrone pour recevoir des messages? ou au moins un moyen de régler ce temps d'attente?Méthode asynchrone pour QueueClient.Receive()?

J'ai trouvé cette méthode BeginReceive de la documentation msdn de QueueClient et j'espérais que ce serait la réponse à ma question mais je ne sais pas comment utiliser cette méthode. Les paramètres de la méthode sont le rappel asynchrone et l'état de l'objet dont je ne sais pas ce qu'ils sont.

Des idées?

MISE À JOUR: Merci à une excellente solution par Sandrino, cela fonctionne asynchrnously. Mais être asynchrone me pose maintenant quelques problèmes. Mon VS plante. Je ne sais pas quel est le problème. Ci-dessous le code que j'utilise.

Travailleur Rôle:

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); 
     } 
    } 

Suis-je manquer sur tout ce qui fait la VS sur le travail et tomber en panne? Parce qu'avant de passer à BeginReceive, quand iw utilisait QueueClient.Receive, cela fonctionnait bien et ne se bloquait pas.

Merci

Répondre

6

La méthode BeginReceive est la voie à suivre dans votre cas. Vous généralement appeler comme ceci:

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

Merci !! Cela fonctionne, c'est asynchrone, mais je ne sais pas pourquoi, mon VS s'est accroché et s'est écrasé trois fois quand j'ai envoyé des messages au bus de service. J'ai mis à jour la question et ajouté du code s'il vous plaît regardez-le et laissez-moi savoir si vous savez quel est le problème. Merci encore – Bitsian

+0

La méthode BeginReceive revient immédiatement, ce qui signifie que votre boucle while est en boucle encore et encore (boucle infinie). Une boucle while comme celle-ci fonctionne bien avec les méthodes synchrones, mais pas quand vous utilisez des appels asynchrones –

+0

Merci je l'ai corrigé en mettant quelques instructions conditionnelles dans la boucle while – Bitsian

1

Ceci est la façon dont je l'ai fait (extension Sandrino De Mattia solution de):

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); 
     } 
    } 
} 

De cette façon, j'ai une « boucle sans fin » avec un mécanisme d'arrêt .

1

La dernière version du Azure SDK ServiceBus (download link) fournit un support complet pour recevoir des messages de manière asynchrone:

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

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

Je ne sais pas pourquoi ils utilisent le synchrone 'Receive () 'dans le tutoriel de démarrage (https://azure.microsoft.com/fr-fr/documentation/articles/service-bus-brokered-tutorial-dotnet/). Quand j'ai essayé de changer cela en attendant 'ReceiveAsync', il a cessé de recevoir des messages! – orad

+0

Nevermind, utilisé 'Task.WaitAll (Queue());' dans la méthode principale et cela a fonctionné! – orad

+0

C'est juste que le tutoriel n'est pas à jour. De toute façon ce n'est pas toujours une bonne chose d'utiliser async. Utilisez juste async quand vous en avez besoin. Quel était le problème avec votre code? – Thomas

Questions connexes