8
votes

MSMQ et interrogation pour recevoir des messages?

J'ai un service Windows qui fait une conversion d'image. Cela fonctionne en licenciant lorsqu'un fichier (dans un dossier particulier) est renommé (c.-à-d. Renommer Rename File Watcher). Fonctionne bien jusqu'à ce que j'ai une quantité massive d'images larguées (et renommées) dans ce dossier. La CPU Redline, etc.

Donc, j'allais changer mon code pour utiliser MSMQ pour faire la queue Tous les fichiers à convertir. Amende. Chaque fois que le fichier est renommé et que l'observateur de fichiers incendie, j'ajoute ensuite un nouveau message à la file d'attente. Kewl.

problème est-ce -> < Comment puis-je saisir un message à la fois de la file d'attente?

Dois-je faire un Objet de minuterie qui interroge la file d'attente toutes les XXX secondes? Ou existe-t-il un moyen de continuer à jeter un coup d'œil au premier élément de la file d'attente. Une fois qu'un message existe, extrayez-le, traitez-le, puis continuez (qui signifie, continuez de me regarder jusqu'à ce que le monde souffle jusqu'à ce que le monde souffle).

Je me suis demandé si j'ai juste besoin de mettre un tandis que la boucle autour de la méthode de réception. Le code PSEDUO est ci-dessous (dans la modification n ° 2) ...

Quelqu'un a une expérience avec cela et avez quelques suggestions?

Merci gentiment!

EDIT:

Si WCF est la voie à suivre, peut-on fournir un exemple de code, etc.

EDIT 2:

Voici quelques pseudo-code je pensais .... xxx


0 commentaires

5 Réponses :


0
votes

On dirait que vous devez regarder dans WCF.

files d'attente dans Windows Communication Foundation

Nivellement de la charge. Envoi d'applications Peut submerger des applications de réception avec des messages. Les files d'attente peuvent gérer Production de message incompatible et Taux de consommation de sorte qu'un récepteur n'est pas submergé.

Voici un exemple en utilisant WCF et MSMQ


2 commentaires

WCF utilise MSMQ derrière les scènes ... Donc je ne sais pas comment WCF m'aide ici.


Veuillez regarder l'exemple dans le lien que j'ai ajouté à ma réponse.



1
votes

J'étais sous l'impression que MSMQ a été construit pour être compatible avec le produit MQ de IBM. Si ce est le cas, vous pouvez appeler MQGET avec un délai d'attente et ne pas vous inquiéter de l'interrogation du tout.

Obtenez un message hors de la file d'attente avec un délai de deux secondes (par exemple). S'il y en avait un, traitez-le. Ensuite, sortez du service si vous le souhaitez ou revenez à la MQGET avec attendre.

Cela signifie que votre service ne sucer pas de temps de processeur inutilement, mais il sera toujours en mesure de sortir de manière opportune s'il est signalé.

Généralement, vous auriez quelque chose comme: xxx


6 commentaires

Salut Pax, je viens de mettre à jour mon poste initial pendant que vous répondiez à cette question. Pouvez-vous s'il vous plaît relire et voir si cela change quelque chose?


Non, pas vraiment. C'est une bonne approche, en supposant que cette période prolongée soit une minute (c'est-à-dire pas trop petite). Vous voulez que ce soit suffisamment grand que vos boucles ne fonctionnent pas continuellement mais petites que vous pouvez réagir à des trucs non msmq. Une partie de cette "substance" sortirait à la véritable boucle si votre service a été dit de fermer.


Et vous voulez seulement appeler DostuffwithMessage si un message a été renvoyé, pas si le délai d'attente est arrivé sans message.


Mais avec le délai d'attente, cela ne va pas continuer à le lire. .. droit?


@Purekrome: Non, si vous lisez un message, cela vient la file d'attente et vous le traitez. Ensuite, lorsque vous revenez à la file d'attente, vous obtiendrez le message suivant . De quoi tu parles me fait couler.


Avec IBM MQ, vous démarreriez une transaction, puis mqget, puis vous supposez que vous le traite avec succès, MQCommand (ou MQRollback si infructueux). Si des choses équivalentes existent dans MSMQ, je ne sais pas avec certitude.



26
votes

Si vous utilisez une file d'attente locale, vous n'avez pas besoin de wcf.

Voici comment a l'air mon exemple de service (un service de service du projet de service Windows): P>

using System.Messaging;
public partial class MQProcessTest1 : ServiceBase
{
    //a name of the queue
    private const string MqName = @".\Private$\test1";
    //define static local private queue
    private static MessageQueue _mq;
    //lazy local property through which we access queue (it initializes queue when needed)
    private static MessageQueue mq
    {
        get
        {
            if (_mq == null)
            {
                if (!MessageQueue.Exists(MqName))
                    MessageQueue.Create(MqName);
                _mq = new MessageQueue(MqName, QueueAccessMode.ReceiveAndAdmin);
                _mq.Formatter = new BinaryMessageFormatter();
            }
            return _mq;
        }
    }

    //constructor
    public MQProcessTest1()
    {
        InitializeComponent();
        //event to process received message 
        mq.ReceiveCompleted += new ReceiveCompletedEventHandler(mq_ReceiveCompleted);
    }

    //method to process message
    private void mq_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
    {
        //queue that have received a message
        MessageQueue cmq = (MessageQueue)sender;
        try
        {
            //a message we have received (it is already removed from queue)
            Message msg = cmq.EndReceive(e.AsyncResult);
            //here you can process a message
        }
        catch
        {
        }
        //refresh queue just in case any changes occurred (optional)
        cmq.Refresh();
        //tell MessageQueue to receive next message when it arrives
        cmq.BeginReceive();
    }

    protected override void OnStart(string[] args)
    {
        //let start receive a message (when arrives)
        if (mq != null)
            mq.BeginReceive();
        //you can do any additional logic if mq == null
    }

    protected override void OnStop()
    {
        //close MessageQueue on service stop
        if (mq != null)
            mq.Close();
        return;
    }
}


2 commentaires

C'est une bonne solution, mais je ne pense pas que cela fonctionne pour les files d'attente transactionnelles (car il n'y a aucune option pour spécifier une transaction dans BeginReceive ou endreceive )


Années passées, mais ... mqname (mqname) - Évitez-la - vous pouvez avoir un problème d'accès à la file d'attente d'autres applications et la gérer manuellement. Créez une file d'attente d'une autre manière. Script PowerShell, manuellement via Windows UI, etc., avec des autorisations spécifiques et ainsi de suite.



0
votes

Sachez que l'exemple de service bloquera à OnStart (). Au lieu de cela, commencez un thread de travailleur:

    protected override void OnStart(string[] args)
    {
        IntPtr handle = this.ServiceHandle;
        myServiceStatus.currentState = (int)State.SERVICE_START_PENDING;
        SetServiceStatus(handle, ref myServiceStatus);

        // Start a separate thread that does the actual work.

        if ((workerThread == null) ||
            ((workerThread.ThreadState &
             (System.Threading.ThreadState.Unstarted | System.Threading.ThreadState.Stopped)) != 0))
        {
            workerThread = new Thread(new ThreadStart(ServiceWorkerMethod));
            workerThread.Start();
        }

    }


2 commentaires

Er - Je ne comprends pas. Donc, c'est un service Windows. Vérifier. Il a une méthode de suralimentation appelée OnStart (..). Vérifier. Je le remplace. Vérifier. Mais maintenant, vous suggérez que quelque chose soit bloqué, alors j'ai besoin de faire certaines de ces nouvelles choses dans un fil plus récent.


Je pense que ce qu'il essaie de dire est ce qui est dit ici .



1
votes

Caster l'événement Args Pour obtenir votre message plutôt que l'expéditeur à un nouvel exemple d'option à Viktorj, c'est sûrement plus efficace? Ensuite, utilisez le champ statique MQ pour appeler Mq.beginreceive, sinon votre mémoire de gravure


0 commentaires