I use the Message Queue to send messages from one application to the other one (this has to work only on one particular machine)
I create the queue like this on the receiver side:
string queueName = ".\\private$\\WZMSGQ";
if (MessageQueue.Exists(queueName))
msgQueue = new MessageQueue(queueName);
else
msgQueue = MessageQueue.Create(queueName, false);
and after this I start the sender application, where I create the queue like that:
msgQueue = new MessageQueue(".\\private$\\WZMSGQ");
in the receiver Application I then retrieve new messages:
Message[] messages = msgQueue.GetAllMessages();
foreach (Message msg in messages){
doSomething();
}
Now I'd like to do two things:
I would like to clear the message queue when instantiating the new MessageQueue instance on the receiver machine such that all old messages are gone.
I'd like to delete the message queue when the program ends, such that it does not exist anymore if I start the application the next time
How can I do that?
MessageQueue.Purge and MessageQueue.Delete seem to be what you want, unless I have misread the question.
Related
Current I'm using Microsoft.Azure.ServiceBus.IQueueClient to RegisterMessageHandler, and then the message I receive is of type Microsoft.Azure.ServiceBus.Message.
According to the documentation:
Message deferral APIs The API is BrokeredMessage.Defer or
BrokeredMessage.DeferAsync in the .NET Framework client,
MessageReceiver.DeferAsync in the .NET Standard client, and
IMessageReceiver.defer or IMessageReceiver.deferAsync in the Java
client.
...but none of those libraries seam to relate to the classes I'm actually using. How do I defer? What classes and stuff do I have to use in order to be able to defer messages? All the samples above dont give enough code snippets to explain it.
Update as requested by #Gaurav
from your answer, I can see my message has that property:
message.ScheduledEnqueueTimeUtc = DateTime.UtcNow.AddHours(1);
but the queueClient also has this method:
queueClient.ScheduleMessageAsync(message, DateTime.UtcNow.AddHours(1));
I'm going to try 'scheduledMessageAsync' as I cant see how to communicate that I've set ScheduledEnqueueTimeUtc without calling the queueClient
Microsoft.Azure.ServiceBus.Message has a property called ScheduledEnqueueTimeUtc. Just set the value of this property to a date/time value in future when you want the message to appear in the queue. Message will be hidden till that time and will only appear in the queue at that date/time.
UPDATE
So I ran a test and confirmed that both ScheduledEnqueueTimeUtc and ScheduleMessageAsync works. I used version 4.1.1 for Microsoft.Azure.ServiceBus SDK.
Here's the code I wrote:
static void Main(string[] args)
{
var connectionString = "my-connection-string";
var queueName = "test";
QueueClient queueClient = new QueueClient(connectionString, queueName);
Message msg1 = new Message()
{
Body = Encoding.UTF8.GetBytes("This message has ScheduledEnqueueTimeUtc property set. It will appear in queue after 2 minutes. Current date/time is: " + DateTime.Now),
ScheduledEnqueueTimeUtc = DateTime.UtcNow.AddMinutes(2)
};
queueClient.SendAsync(msg1).GetAwaiter().GetResult();
Message msg2 = new Message()
{
Body = Encoding.UTF8.GetBytes("This message is sent via ScheduleMessageAsync method. It will appear in queue after 2 minutes. Current date/time is: " + DateTime.Now)
};
queueClient.ScheduleMessageAsync(msg2, new DateTimeOffset(DateTime.UtcNow.AddMinutes(2))).GetAwaiter().GetResult();
Console.ReadLine();
}
And this is what I see when I fetch the messages in Peek-Lock mode:
Using the message deferral APIs like BrokeredMessage.Defer or BrokeredMessage.DeferAsync will defer the message.
Defering a message will change the state of the message from Active to Deferred. The message can be later retrieved based on the sequence number.
ScheduleMessageAsync() is used to schedule the delivery of message (sends a message at specified time). It cannot be used after receiving a message.
I've coded the solution I was looking for, here is the basic outline:
inside an asynchronous method (runs its own thread)
public async Task InitialiseAndRunMessageReceiver()
start an infinite loop that reads the message
receiver = new MessageReceiver(serviceBusConnectionString, serviceBusQueueName, ReceiveMode.PeekLock);
while (true) { var message = await receiver.ReceiveAsync(); ... more code... }
once you know you are about to start your long task, defer the message, but store the message.SystemProperties.SequenceNumber. this keeps it in the queue but prevents it from being re-delivered.
await receiver.DeferAsync(message.SystemProperties.LockToken);
and when you finally done ask for the message again using the message.SystemProperties.SequenceNumber, and complete the message as if it weren't deferred
var message = receiver.ReceiveDeferredMessageAsync(message.SystemProperties.SequenceNumber);
receiver.CompleteAsync(message.Result.SystemProperties.LockToken);
and your message will be removed from the queue.
much of my confusion was caused by the libraries being named similarly with overlapping lifespans.
Microsoft.Azure.ServiceBus.Core.MessageReceiver is the message receiver above
Old question, but what suited my situation was deleting the message and posting a copy using ScheduleMessageAsync (there is a copy method somewhere). Then the message would just come back at the desired time.
I'm trying to get messages from a MSMQ queue, my problem occurs when I have messages in my queue and I execute my thread, it was cleaning the queue when this code runs:
queue = new MessageQueue(queueName);
It means that I'm overriding the queue that had itens, them my question is: how can I get my previously created queue?
EDIT:
I'm looking for a method like GetPrivateQueueByLabel, but I didn't found!
Use Following Code in place of your code
//queue = new MessageQueue();
if(queue.Path==null)
{
queue.Path = queueName;
}
//now use queue object for further process
so that your queue is not replace by previous queue with same name and Microsoft will not allow to create different queue with same name so if queue with same name is already present then it has been used else new queue is create.
Also as per your EDIT your searching for GetPrivateQueueByLabel Method apart from that you can use following code snippet which return array of all private Queue in your Machine (or machine Name which you Provide)
using System.Net;
using System.Messaging;
MessageQueue[] privatequeuelist = MessageQueue.GetPrivateQueuesByMachine(Dns.GetHostName());
I'm trying to resubmit a message from a deadletter queue.
I am can replay a message on a dead letter queue, thats fine.
The problem is when I want to now delete this from the deadletter queue.
Here is what I am trying to do:
var subscription = "mySubscription";
var topic = "myTopic";
var connectionString = "connectionStringOnAzure";
var messagingFactory = MessagingFactory.CreateFromConnectionString(connectionString);
var messageReceiver = messagingFactory.CreateMessageReceiver(SubscriptionClient.FormatDeadLetterPath(topic, subscription), ReceiveMode.ReceiveAndDelete);
long messageSequenceNumber = 835;
var brokeredMessage = messageReceiver.Receive(messageSequenceNumber); // this part fails
// mark message as complete to remove from the queue
brokeredMessage.Complete();
I get following error message:
Microsoft.ServiceBus.Messaging.MessageNotFoundException : Failed to lock one or more specified messages. The message does not exist..TrackingId:ae15edcc-06ac-4d2b-9059-009599cf5c4e_G5_B15,TimeStamp:8/13/2013 1:45:42 PM
However, instead of specifying a message sequence number and I just use the ReceiveBatch as shown below, it is fine.
// this works and does not throw any errors
var brokeredMessages = messageReceiver.ReceiveBatch(10);
Am I missing something? Or is there another way of reprocessing deadletters and removing them?
The deadletter queue is processed in sequence just like any other queue.
The Receive(seqNo) method is used in combination with Defer(), which puts the message into a different secondary Queue - the "deferral queue". The deferral queue exists for scenarios where you are getting messages out of the expected order (eg. in a state machine) and need a place to put the messages that arrived early. Those you can park with Defer() and make a note of that (probably even in session state) and then pull the messages once you're ready to do so. The Workflow Manager runtime used by SharePoint uses that feature, for instance.
After creating receiver you can politely start receiving all messages (without being picky) till you encounter message with your SequenceNumber, call Complete() on the message and stop iterating the queue. i.e
while (true)
{
BrokeredMessage message = receiver.Receive();
if (message.SequenceNumber == sequenceNumber)
{
message.Complete();
break;
}
}
Without completing message it remains in the queue and that's what you want (at least in .NET 4.5. Worth to note that if your Sequence Number is not found Receiver will loop the queue indefinitely.
I have a WCF on a Web Role and then a Worker Role to process the messages added to an azure queue by the WCF.
I am doing the following :
var queue = queueStorage.GetQueueReference("myqueue");
var message = new CloudQueueMessage(string.Format("{0},{1}", pWord,processed));
queue.AddMessage(message);
Then I want to wait until the message has been processed, but I dont know if my queue object will get updated on its own or I have to do something about it.
On my worker role I have the following :
This is my onStart method :
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
inputQueue = queueClient.GetQueueReference("myqueue");
And then on my Run method :
while (true)
{
try
{
// Retrieve and process a new message from the queue.
msg = inputQueue.GetMessage();
if (msg != null)
{
result = processMessage(msg);
On my processMessage method :
var messageParts = msg.AsString.Split(new char[] { ',' });
var word = messageParts[0];
var processed = Convert.ToBoolean(messageParts[2]);
word = "recibido";
processed = true;
addMessageToQueue2(userId,processed);
return 1;
Add message to queue is :
var queue = outputQueue.GetQueueReference("myQueue");
var message = new CloudQueueMessage(string.Format("{0},{1}", pWord, pProcessed));
queue.AddMessage(message);
Im fairly new to queues but I think this should work so all I need is just waiting until the message has been processed but dont know how it internally works.
Not quite sure what you mean by waiting until the message has been processed. With Azure queues, the operation is very simple:
Place messages on queue (with message TTL)
Read message(s) from queue (with processing-timeout). This processing timeout says "I promise to finish dealing with this message, and then deleting this message, before this timeout is hit.
The queue message stays in the queue but becomes invisible to all other readers during the timeout period.
The message-reader then deletes the message from the queue.
Assuming the code that read the queue message deletes the message before the promised timeout expires, all is good in QueueLand. However: If the processing goes beyond the timeout period, then the message becomes visible again. And... if someone else then reads that message, the original reader loses rights to delete it (they'll get an exception when making an attempt).
So: Long story short: You can process a message for as long as you want, within the stated timeout period, and then delete it. If your code crashes during processing, the message will eventually reappear for someone else to read. If you want to deal with poison messages, just look at the DequeueCount property of the message to see how many times it's been read (and if over a certain threshold, do something special with the message, like tuck it away in a blob or table row for future inspection by the development team).
See this article for all documented queue limits (and a detailed side-by-side comparison with Service Bus Queues).
I have a mainform that sends messages and a random number of receive forms that run as separate application (C# 4.0).
Everytime one of the random number of forms receive's the message but than the message is received and the others won't receive it anymore.
I've tried this with UDP, TCP IP, MSMQ but I don't seem to get it working well. The sender and receivers run on the same system.
Can anyone recommend me a way to broadcast a message that stays in a sort of queue till all the forms have received it, or maybe it can stay in that queue till the application closes, but how...?
Thanks in advance people!
Kind regards
Wesley
Multicast MSMQ
You can use MSMQ with Multicast option (check that your Windows installation has that option before trying it, you will find it in the "add/remove windows features" section of the Windows control panel).
A sender using the MSMQ Multicast Queue will submit a message that can be processed by many MSMQ Multicast Queue receivers.
Receiver
The reader must have a private queue, then you will need to set the multicast address that you want to use (the choice of the multicast address is arbitrary, that's why you will often see the same address mentionned in different posts, see the msdn docs for more information), like this:
var myQueue = MessageQueue.Create(".\private$\MulticastTest", false);
myQueue.MulticastAddress = "234.1.1.1:8001";
or directly use the existing multicast queue (if it has been created with the multicast address) the standard way:
var myQueue = new MessageQueue(multicastQueueName());
Then you will have to listen for new messages using your prefered method, I prefer to use this one:
myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
myQueue.PeekCompleted += new PeekCompletedEventHandler(QueuePeekCompleted);
myQueue.BeginPeek();
The delegate QueuePeekCompleted looks like this:
private void QueuePeekCompleted(object sender, PeekCompletedEventArgs e)
{
try
{
var message = myQueue.EndPeek(e.AsyncResult);
//LogInfo("Received this : " + message.Body);
}
catch (Exception ex)
{
//LogError(ex);
}
myQueue.Receive();
myQueue.BeginPeek();
}
Sender
The sender of a multicast message must connect to the multicast queue like this:
MessageQueue myQueue = new MessageQueue("formatname:multicast=234.1.1.1:8001");
Then send a message as usual:
myQueue.Send("hey listen!");
The messaging pattern you are looking for is called publish-subscribe. MSMQ does not support this messaging pattern natively.
However there are a number of open source tools which do including RabbitMQ and NServiceBus.