I'm using ActiveMQ to send and receive messages using a C# app. However I'm having some difficulty just getting a count of the messages in the queue.. Here's my code:
public int GetMessageCount()
{
int messageCount = 0;
Uri connecturi = new Uri(this.ActiveMQUri);
IConnectionFactory factory = new NMSConnectionFactory(connecturi);
using (IConnection connection = factory.CreateConnection())
using (ISession session = connection.CreateSession())
{
IDestination requestDestination = SessionUtil.GetDestination(session, this.QueueRequestUri);
IQueueBrowser queueBrowser = session.CreateBrowser((IQueue)requestDestination);
IEnumerator messages = queueBrowser.GetEnumerator();
while(messages.MoveNext())
{
messageCount++;
}
connection.Close();
session.Close();
connection.Close();
}
return messageCount;
}
I thought I could use the QueueBrowser to get the count, but the IEnumerator it returns is always empty. I got the idea of using QueueBrowser from this page, but maybe there is another way I should be doing this?
Update:
The solution to the 'infinite loop' issue I found when going through the enumerator was solved by accessing the current message. It now only goes through the loop once (which is correct as there is only one message in the queue).
New while loop is:
while(messages.MoveNext())
{
IMessage message = (IMessage)messages.Current;
messageCount++;
}
I don't have an ActiveMq with me right now so I can not try it
but I think the problem is you are not starting the connection. Try like this :
using (IConnection connection = factory.CreateConnection())
{
connection.start ();
using (ISession session = connection.CreateSession())
{
//Whatever...
}
}
Related
The exception in my questions title is being thrown on the line return allMessages; in the code below. I don't understand it because that line of code is still within the using (var sslStream...) statement, so by the time it is executed the SslStream object should not be disposed..
public static List<Message> FetchAllMessages(string hostname, int port, string username, string password, string proxyIp, int proxyPort)
{
// The client disconnects from the server when being disposed
using (Pop3Client client = new Pop3Client())
{
var proxyClient = new HttpProxyClient(proxyIp, proxyPort);
using (var sslStream = new SslStream(proxyClient.CreateConnection(hostname, port).GetStream()))
{
sslStream.AuthenticateAsClient(hostname);
client.Connect(sslStream);
// Authenticate ourselves towards the server
client.Authenticate(username, password);
// Get the number of messages in the inbox
int messageCount = client.GetMessageCount();
// We want to download all messages
List<Message> allMessages = new List<Message>(messageCount);
// Messages are numbered in the interval: [1, messageCount]
// Ergo: message numbers are 1-based.
// Most servers give the latest message the highest number
for (int i = messageCount; i > 0; i--)
{
allMessages.Add(client.GetMessage(i));
}
// Now return the fetched messages
return allMessages;
}
}
}
UPDATES:
Put a breakpoint on return allMessages; and hovered over the sslStream object, it is not disposed.
When I remove the using statement and just declare var sslStream it works but I don't think this would scale well without it..
So, I don't really have an explanation as to why, but restarting my computer solved the problem, the code runs fine after doing that...
I'm making examples for my ZeroMQ CLR namespace, however I have a problem with PUB/SUB.
Why do I get only the first message? Sometimes I get no message, if I debug through the client (on PubSub_Client(arg);) I get some messages.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Security.Cryptography;
using ZeroMQ;
namespace ZeroMQ.Test
{
static partial class Program
{
static string PubSub_FrontendAddress = "tcp://127.0.0.1:2772";
public static void Main(string[] args)
{
if (args == null || args.Length < 1)
{
// say here were some arguments...
args = new string[] { "World" };
}
// Setup the ZContext
context = ZContext.Create();
CancellationTokenSource cancellor0 = null;
{
// Create the "Server" cancellor and threads
cancellor0 = new CancellationTokenSource();
var serverThread = new Thread(PubSub_Server);
serverThread.Start(cancellor0.Token);
serverThread.Join(64);
}
{
Thread.Sleep(1000);
Console.WriteLine("Starting...");
// foreach arg we are the Client, asking the Server
foreach (string arg in args)
{
PubSub_Client(arg);
// Thread.Sleep(1000);
}
Console.WriteLine("Ended...");
}
if (cancellor0 != null)
{
// Cancel the Server
cancellor0.Cancel();
}
// we could have done here context.Terminate()
}
static void PubSub_Server(object cancelluS)
{
var cancellus = (CancellationToken)cancelluS;
using (var socket = ZSocket.Create(context, ZSocketType.SUB))
{
socket.Bind(PubSub_FrontendAddress);
socket.SubscribeAll();
/* var poller = ZPollItem.Create(socket, (ZSocket _socket, out ZMessage message, out ZError _error) =>
{
while (null == (message = _socket.ReceiveMessage(/* ZSocketFlags.DontWait, * out _error)))
{
if (_error == ZError.EAGAIN)
{
_error = ZError.None;
Thread.Sleep(1);
continue;
}
throw new ZException(_error);
}
return true;
}); /**/
while (!cancellus.IsCancellationRequested)
{
ZError error;
ZMessage request;
/* if (!poller.TryPollIn(out request, out error, TimeSpan.FromMilliseconds(512)))
{
if (error == ZError.EAGAIN)
{
error = ZError.None;
Thread.Sleep(1);
continue;
}
throw new ZException(error);
} /**/
if (null == (request = socket.ReceiveMessage(ZSocketFlags.DontWait, out error)))
{
if (error == ZError.EAGAIN)
{
error = ZError.None;
Thread.Sleep(1);
continue;
}
throw new ZException(error);
} /**/
foreach (ZFrame frame in request)
{
string strg = frame.ReadString();
Console.WriteLine("{0} said hello!", strg);
}
}
socket.Unbind(PubSub_FrontendAddress);
}
}
static void PubSub_Client(string name)
{
using (var socket = ZSocket.Create(context, ZSocketType.PUB))
{
using (var crypto = new RNGCryptoServiceProvider())
{
var identity = new byte[8];
crypto.GetBytes(identity);
socket.Identity = identity;
}
socket.Connect(PubSub_FrontendAddress);
using (var request = new ZMessage())
{
request.Add(new ZFrame(name));
socket.Send(request);
}
socket.Disconnect(PubSub_FrontendAddress);
}
}
}
}
I'm having trouble with your design which seems just wrong:
A single subscriber and multiple publishers is an odd choice. I trust you have a good reason for it, but you should have said what that is. When sending messages from multiple clients to a single server, it is normal to use DEALER/ROUTER sockets instead. PUB/SUB is intended for a small set of publishers to a large number of subscribers.
A client that connects, sends one message, then immediately disconnects, is another very unusual use case that I hope is just an example:
For one thing, you are open to linger problems whereby the message will get dropped on the disconnect it is isn't sent within the linger timeout. [I don't know what the default linger is for your language binding, so that may or may not be an issue, but you should at least check to ensure that it isn't.]
For another, as you've already found, there are issues around the time it takes to connect to a socket, which may lead to PUB messages getting dropped if they are sent before the socket has properly connected.
If you insist on using PUB/SUB in this manner, you will need an out of band protocol to synchronise the PUB and SUB threads before the pub messages are sent. There are examples of how to do this reliable pub/sub in the zeromq guide. This will involve a second set of sockets in the same threads to send the synchronisation messages; DEALER sockets don't drop messages which is why they are suitable for that purpose...
But, DEALER/ROUTER sockets would appear to be a better choice than PUB/SUB unless there is some design requirement that hasn't been disclosed.
Well... There was a comment by Martin Sustrik: "The problem is that connecting is asynchronous and takes certain amount of time."
Now there is Thread.Sleep(64) - and it works...:
static void PubSub_Client(string name)
{
using (var socket = ZSocket.Create(context, ZSocketType.PUB))
{
socket.Connect(PubSub_FrontendAddress);
Thread.Sleep(64);
using (var request = new ZMessage())
{
request.Add(new ZFrame(name));
socket.Send(request);
}
socket.Disconnect(PubSub_FrontendAddress);
}
}
Do you know any better way to get the connection established?
The following code creates a new thread acting first as a named pipe client for sending parameters and then as a server for retrieving results. After that it executes a function in another AppDomain acting as a named pipe server and after that as a client to send the results back.
public OrderPrice DoAction()
{
Task<OrderPrice> t = Task<OrderPrice>.Factory.StartNew(NamedPipeClient, parameters);
if (domain == null)
{
domain = AppDomain.CreateDomain(DOMAINNAME);
}
domain.DoCallBack(AppDomainCallback);
return t.Result;
}
static OrderPrice NamedPipeClient(object parameters) {
OrderPrice price = null;
using (NamedPipeClientStream stream = new NamedPipeClientStream(PIPE_TO)) {
stream.Connect();
SerializeToStream(stream, parameters);
}
using (NamedPipeServerStream stream = new NamedPipeServerStream(PIPE_BACK)) {
stream.WaitForConnection();
price = (OrderPrice)DeserializeFromStream(stream);
}
return price;
}
void AppDomainCallback() {
OrderPrice price = null;
using (NamedPipeServerStream stream = new NamedPipeServerStream(PIPE_TO)) {
stream.WaitForConnection();
List<object> parameters = (List<object>)DeserializeFromStream(stream);
if (mi != null)
price = (OrderPrice)mi.Invoke(action, parameters.ToArray());
}
using (NamedPipeClientStream stream = new NamedPipeClientStream(PIPE_BACK)) {
stream.Connect();
SerializeToStream(stream, price);
}
}
The code is called once per second on average and it worked fine for 7+ hours. But at some point "system.io.ioexception all pipe instances are busy" is thrown and they wont reconnect anymore after that. Browsing here it seems like it could be because of not properly disposing the pipe objects, but I guess thats all good since they are inside using statements.
Does anyone have any clue what could be wrong here? The code is in .NET 4.0 running on windows server 2008.
Sounds like it should be a mutex instead of a simple lock
Lock, mutex, semaphore... what's the difference?
as far as the occasional halting, it could be starvation or a deadlock.
This is good reading material for abstracts on what may be happening
http://en.wikipedia.org/wiki/Dining_philosophers_problem
I'm trying to do get a basic interface working for Windows Store using the Windows.Networking.Sockets API. So far I have this:
public async void Test()
{
using (var socket = new StreamSocket())
{
socket.Control.KeepAlive = false;
socket.Control.NoDelay = false;
await socket.ConnectAsync(new HostName("192.168.1.1"), "5555", SocketProtectionLevel.PlainSocket);
using (var writer = new DataWriter(socket.OutputStream))
{
writer.UnicodeEncoding = UnicodeEncoding.Utf8;
writer.WriteString("yea!");
//writer.WriteByte(0x50); //this doesn't work either to send raw ASCII
var t = writer.FlushAsync();
while (t.Status != AsyncStatus.Completed) ; //just in case?
}
}
}
So far, I do appear to get a successful connect and disconnect. However, I never get any text received.
My netcat command (running under an OpenBSD router)
$ nc -lv 5555
If I don't have netcat running when I run the Test function, it will throw an exception and all that as well as expected. What am I doing wrong here?
This makes absolutely no sense to me, but apparently StoreAsync is required on the DataWriter. I would've thought that Flush should've called that, but apparently not. Yet another fun part about the WinRT APIs. My fixed code:
using (var socket = new StreamSocket())
{
socket.Control.KeepAlive = false;
socket.Control.NoDelay = false;
await socket.ConnectAsync(new HostName("192.168.1.1"), "5555", SocketProtectionLevel.PlainSocket);
using (var writer = new DataWriter(socket.OutputStream))
{
writer.UnicodeEncoding = UnicodeEncoding.Utf8;
writer.WriteString("yea!");
await writer.StoreAsync();
}
}
I'm using ActiveMQ 5.6.0 and ActiveMQ NMS client.
I connect to the broker using the follow code:
var connectionFactory = new ConnectionFactory(
"failover:(tcp://localhost:61616)?transport.timeout=5000"
);
connection = connectionFactory.CreateConnection();
connection.Start();
connection.ConnectionResumedListener += OnConnectionResumed;
Then I stop the broker and start it again. After that in the method OnConnectionResumed
private void OnConnectionResumed()
{
var session = connection.CreateSession();
...
}
I always get the failover timeout exception when try to create a session.
What am I doing wrong?
Thanks
This problem appeared because I had created a session in the thread where the
resumed call is made in.
The correct code is:
private void OnConnectionResumed()
{
Task.Factory.StartNew(() =>
{
var session = connection.CreateSession();
...
});
}