RabbitMQ and SharedQueue closed - c#

Im using RabbitMQ to send simple short int information, first I'm sending id to one project like that:
private void SendPgcIdToRabbitMQ(string id)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
bool durable = true;
channel.QueueDeclare("XQueue", durable, false, false, null);
var body = Encoding.UTF8.GetBytes(id);
channel.BasicPublish("", "XQueue", null, body);
Console.WriteLine(" [x] Sent {0}", id);
}
}
}
and listener of it:
public void Listener()
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare("XQueue", true, false, false, null);
var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume("XQueue", false, consumer);
Console.WriteLine(" [*] Waiting for messages. " +
"To exit press CTRL+C");
while (true) {
var ea =
(BasicDeliverEventArgs)consumer.Queue.Dequeue();
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
AddPGCFileID(message);
channel.BasicAck(ea.DeliveryTag, false);
Thread.Sleep(500);
}
}
}
}
It works fine, so after receiving message I'm processing some operation wit it, then I get second ID and create other queue to do this same:
private void SendSurveyIdToRabbitMQ(int yID)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection()) {
using (var channel = connection.CreateModel()) {
bool durable = true;
channel.QueueDeclare("YQueue", durable, false, false, null);
var body = Encoding.UTF8.GetBytes(yID.ToString());
channel.BasicPublish("", "YQueue", null, body);
Console.WriteLine(" [x] Sent {0}", yID);
}
}
}
and receive:
public void InquiryListener()
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection()) {
using (var channel = connection.CreateModel()) {
channel.QueueDeclare("YQueue", true, false, false, null);
var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume("YQueue", false, consumer);
Console.WriteLine(" [*] Waiting for messages. " +
"To exit press CTRL+C");
while (true) {
var ea =
(BasicDeliverEventArgs)consumer.Queue.Dequeue();
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
StartProcessing(Convert.ToInt32(message));
channel.BasicAck(ea.DeliveryTag, false);
Thread.Sleep(500);
}
}
}
}
First queue sending and receiving works fine but at second I get:
It is strange because it was working that way, from some time I'm geting this problem. I whas reseting rabbitmq, removin all queues etc. can't find where is a problem. Any ideas?
edit:
I whas debuging to know if second process is ending properly (eariel crash on second proces don't cause problem with rabbitmq) and it passed, I whas supriced because no error ocurs on YQueue, but after about minute of working my process (only waiting, non incomming message, non processing) I gey this same exception on XQueue

Check first if the queue is empty before executing while(true){ ... }.

Related

How to send acknowledgment (Consumer) in RabbitMQ externally?

I have an application where it sending message to RMQ broker as below:
var connectionFactory = new ConnectionFactory()
{
HostName = "localhost"
};
using (var connection = connectionFactory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare("demo",
durable:true,
exclusive:false,
autoDelete:false,
arguments:null);
Console.WriteLine("Click enters to send random case Id");
do
{
Console.ReadLine();
var message = new {CaseId = new Random().Next()};
var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message));
channel.BasicPublish("", "demo", null, body);
Console.WriteLine("Successfully send message.");
} while (true);
}
}
It successfully sent the message.
There is another app called the consumer app.
The code is below:
private void InitiateRabbitMq()
{
var connectionFactory = new ConnectionFactory()
{
HostName = "localhost"
};
var connection = connectionFactory.CreateConnection();
var channel = connection.CreateModel();
MessageHandler messageReceiver = new MessageHandler(channel);
channel.BasicConsume("demo", false, messageReceiver);
}
The message handler is:
public class MessageHandler : DefaultBasicConsumer
{
private readonly IModel _channel;
public MessageHandler(IModel channel)
{
_channel = channel;
}
public override async void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey,
IBasicProperties properties, ReadOnlyMemory<byte> body)
{
var message = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(body.ToArray()));
_processor.process(message);
}
}
Here is the process method parth which is another class:
client.BeginTransfer(transfer,
HandleUploadProgressChanged,
HandleUploadComplete,
HandleUploadInterrupted,
HandleUploadCancelled,
3600,
UploadFilesFinishedCallback);
Once begin transfer completed. It invoked UploadFilesFinishedCallback . I want to acknowledge in this method. How can I do it?
This is how you Acknowledge message:
channel.BasicAck(deliveryTag, false);
So it means your Function "UploadFilesFinishedCallback" must have the deliveryTag
==> and this means that also your "process" function must have the deliveryTag (which currently gets only the message content)
solution:
add new parameter "deliveryTag" to function "process", and to function "UploadFilesFinishedCallback"
you can use it in the callback like this:
client.BeginTransfer(transfer,
HandleUploadProgressChanged,
HandleUploadComplete,
HandleUploadInterrupted,
HandleUploadCancelled,
3600,
() => { UploadFilesFinishedCallback(deliveryTag) });
(depends on the signature of the callback function)

Problem with RabbitMQ and deduplication plugin

I'm a RabbitMQ newbie; for a new project I need to use the deduplication plugin. I'm using AspNet Core 3.0 worker process and language is C#.
I've tried a very simple example, 2 publishers sending 10 messages numbered 1 to 10 and one consumer getting messages and acknowledging them.
I'm having quite strange and unpredictable results:
if I run the 3 workers (2 Publishers and one consumer) inside the same process, it looks like that deduplication plugin works fine and inserts in the queue only 10 unique messages, but the consumer reads only the first 2 and ackowledges only one of them.
if I run publishers and consumer in two different processes, the consumer gets all the 10 messages but after ack the messages remain in the queue and if I run again the consumer process they get reprocessed again.
I've tried to google for some full working sample in C# for deduplication, but without success
Publisher
int cnt = 1;
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
Dictionary<string, object> dd = new Dictionary<string, object>();
dd["x-message-deduplication"] = true;
channel.QueueDeclare(queue: qname,
durable: true,
exclusive: false,
autoDelete: false,
arguments: dd);
while (!stoppingToken.IsCancellationRequested)
{
var message = GetMessage(cnt);
var body = Encoding.UTF8.GetBytes(message);
var properties = channel.CreateBasicProperties();
properties.Persistent = true;
Dictionary<string, object> d = new Dictionary<string, object>();
d["x-deduplication-header"] = cnt;
properties.Headers = d;
channel.BasicPublish(exchange: "",
routingKey: qname,
basicProperties: properties,
body: body);
Console.WriteLine(" [x] Sent {0}", message);
logDB(cnt, "Sender"+Wname);
cnt++;
if (cnt > 10)
break;
await Task.Delay(1000, stoppingToken);
}
Consumer:
while (!stoppingToken.IsCancellationRequested)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
Dictionary<string, object> dd = new Dictionary<string, object>();
dd["x-message-deduplication"] = true;
channel.QueueDeclare(queue: qname,
durable: true,
exclusive: false,
autoDelete: false,
arguments: dd);
_logger.LogInformation("{0} Waiting for messages.", Cname);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
_logger.LogInformation("{0} Received {1}", Cname, message);
string[] parts = message.Split('-');
int cntmsg = int.Parse(parts[1]);
logDB(cntmsg, Cname);
Thread.Sleep((cntmsg % 5) * 1000);
_logger.LogInformation("{0} Received {1} done", Cname, message);
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: true);
};
channel.BasicConsume(queue: qname,
autoAck: false,
consumer: consumer);
_logger.LogInformation("{0} After BasicConsume", Cname);
while (true)
await Task.Delay(1000, stoppingToken);
}
after contacting the developer of the deduplication plugin it turned out the problem was related to the type (int) of deduplication header, using a string value works.
He will release a new version supporting int datatype soon.

UWP app cannot receive, only send, using sockets

I'm currently developing an UWP app which should have capability to be as a TCP server (using ports) so client can connect to it via other device and send requests and server responds with data.
I followed the Socket example on :Microsoft site, and got sample code working (in which server and client are both in same app)
I changed IP addresses and ports so i could use apps on 2 different machines with direct connection, I also made separate simple client application, using sample code from Here
Now problem is as follows: UWP app can successfully communicate with its own client method provided by Microsoft's sample, but is unable to communicate with console client program I made and was running on other. UWP can indeed connect with client and also send data, but it cannot receive data, the function streamReader.ReadLineAsync(); will wait infinitely long and that's all.
How do i make UWP app get the message client is sending and what i might be doing wrong ?
public sealed partial class MainPage : Page
{
static string PORT_NO = "1300";
const string SERVER_IP = "192.168.0.10";
public MainPage()
{
this.InitializeComponent();
outputText.Text = "Helloo";
StartConnection(SERVER_IP, PORT_NO);
//StartClient();
}
public async void StartConnection(string net_aadress, string port_nr)
{
try
{
var streamSocketListener = new StreamSocketListener();
// The ConnectionReceived event is raised when connections are received.
streamSocketListener.ConnectionReceived += this.StreamSocketListener_ConnectionReceived;
// Start listening for incoming TCP connections on the specified port. You can specify any port that's not currently in use.
await streamSocketListener.BindServiceNameAsync(port_nr);
outputText.Text = "server is listening...";
}
catch (Exception ex)
{
Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
outputText.Text = (webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
}
}
private async void StreamSocketListener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender, Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args)
{
string request = "password";
string second;
/*
using (var streamReader = new StreamReader(args.Socket.InputStream.AsStreamForRead()))
{
request = await streamReader.ReadLineAsync();
}
*/
//await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server received the request: \"{0}\"", request)));
// Echo the request back as the response.
using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
using (var streamReader = new StreamReader(args.Socket.InputStream.AsStreamForRead()))
{
second = await streamReader.ReadLineAsync();
}
using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(second);
await streamWriter.FlushAsync();
}
}
//await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server sent back the response: \"{0}\"", request)));
sender.Dispose();
//await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add("server closed its socket"));
}
private async void StartClient()
{
try
{
// Create the StreamSocket and establish a connection to the echo server.
using (var streamSocket = new Windows.Networking.Sockets.StreamSocket())
{
// The server hostname that we will be establishing a connection to. In this example, the server and client are in the same process.
var hostName = new Windows.Networking.HostName("localhost");
//this.clientListBox.Items.Add("client is trying to connect...");
await streamSocket.ConnectAsync(hostName, PORT_NO);
//this.clientListBox.Items.Add("client connected");
// Send a request to the echo server.
string request = "Hello, World!";
using (Stream outputStream = streamSocket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
//this.clientListBox.Items.Add(string.Format("client sent the request: \"{0}\"", request));
// Read data from the echo server.
string response;
using (Stream inputStream = streamSocket.InputStream.AsStreamForRead())
{
using (StreamReader streamReader = new StreamReader(inputStream))
{
response = await streamReader.ReadLineAsync();
}
}
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
() =>
{
outputText.Text = "Client got back " + response;
}
);
}
//this.clientListBox.Items.Add("client closed its socket");
}
catch (Exception ex)
{
Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
//this.clientListBox.Items.Add(webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
}
}
}
Here is source code for Client application:
{
class Program
{
const int PORT_NUMBER = 1300;
const string SERVER_IP = "192.168.0.10";
static void Main(string[] args)
{
string textToSend = DateTime.Now.ToString();
string password = "Madis on loll";
string receiveddata;
try
{
Console.WriteLine("Client progrm started");
TcpClient client = new TcpClient(SERVER_IP, PORT_NUMBER);
NetworkStream nwStream = client.GetStream();
//System.Threading.Thread.Sleep(500);
//see, how long is packet
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
Console.WriteLine("Received : " + Encoding.ASCII.GetString(bytesToRead, 0, bytesRead));
byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
Console.WriteLine("Sending : " + password);
nwStream.Write(password2, 0, password2.Length); //sending packet
byte[] receiveddata2 = new byte[client.ReceiveBufferSize];
int receiveddatalength = nwStream.Read(receiveddata2, 0, client.ReceiveBufferSize);
Console.WriteLine("Received : " + Encoding.ASCII.GetString(receiveddata2, 0, bytesRead));
}
catch (Exception ex)
{
Console.WriteLine("Connection error");
}
}
}
}
Found answer myself: main problem is with ReadLineAsync() in Server program: it waits and collects all the stream until it gets end of line character. In this case end of line was never sent and therefore server kept waiting infinitely.
Simplest fix was on Client side by simply adding end of line at the end of packet, like this:
before:
byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
Console.WriteLine("Sending : " + password);
nwStream.Write(password2, 0, password2.Length); //sending packet
after:
byte[] newLine = Encoding.ASCII.GetBytes(Environment.NewLine);
byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
Console.WriteLine("Sending : " + password);
nwStream.Write(password2, 0, password2.Length); //sending packet
nwStream.Write(newLine,0,newLine.Length);
Also 1 thing worth mentioning: current StreamSocketListener_ConnectionReceived is able to send only once, then it sets outputStream.CanWrite to false.
This can be solved by removing using() from writing and reading functions, like this:
before:
PS! Manually flushing is also replaced with autoflush.
using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
{
using (var streamWriter = new StreamWriter(outputStream))
{
await streamWriter.WriteLineAsync(request);
await streamWriter.FlushAsync();
}
}
after:
Stream outputStream = args.Socket.OutputStream.AsStreamForWrite();
var streamWriter = new StreamWriter(outputStream);
streamWriter.AutoFlush = true;
await streamWriter.WriteLineAsync(request);
Hope it helps someone someday.

Named Pipe Input Output in C#

I am working with named pipes and very confused about how the interaction between the client and server is happening.
My server is a VM with a named pipe attached to it. I have created a client stream in C# this way:
NamedPipeClientStream client = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut);
Let's say the VM prompt is like below:
Hello!
Do you accept (y/n): y
Text1 : 1.2.3.4
Text2 : 2.3.4.5
What I essentially need to do is, check if the line read by the stream is "Do you accept (y/n):", if it matches then write y to the stream.es with Text1, then write 1.2.3.4 in the stream
Problems I am facing:
The prompt doesn't display anything after Hello!. What I thought
is, it is maybe waiting for the next input. So, instead of doing
this:
if(line.contains("Do you accept (y/n):"))
writer.writeLine("y")
I did this:
if(line.contains("Hello!"))
writer.writeLine("y");
Is this the correct thing? If it is, then it means that the server
isn't pushing the text in the buffer on which it is awaiting input.
So, every time I'll have to do the check for the previous line and
write the output of the next expected line to the writer stream?
Also, as per above, for passing 1.2.3.4 for Text1, I did this:
if(line.contains("Do you accept (y/n):"))
writer.writeLine("1.2.3.4")
What appears in my execution prompt is: Text1 : 1111111 ie. it's
only repeating the first character of the input I have passed. Why
such? I have already set AutoFlush = true to my writer stream.
Any pointers here will be highly appreciated!
Edit: Including the snippet
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Windows;
namespace App1 {
static void Main(string [] args) {
NamedPipeClientStream client = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut);
while(!client.IsConnected);
Streamreader reader = new StreamReader(client);
StreamWriter writer = new StreamWriter(client);
string line = "";
writer.AutoFlush = true;
while((line = reader.readLine()) != null) {
if(line.Contains("Hello!") {
writer.writeLine("1.2.3.4"); // input for the next prompt
}
else if(line.Contains("Text1") {
writer.writeLine("2.3.4.5"); // input for next prompt of Text2
}
writer.Flush();
writer.WaitForPipeDrain();
}
}
}
Is above the right way?
Also, sometimes the pipe reader is missing data. Like it shows Tet1 instead of Text1. Why such?
You have this statement: while(!client.IsConnected); which causes the client to wait for the connection before proceeding. However, the client never attempts to connect (client.Connect();), so presumably you will be waiting forever. Replace that line with if (!client.IsConnected) {client.Connect();} to get this to work.
Beyond that, per the comments, without knowing what your server side code looks like it's hard to say what the client should be sending; as the two sides are having a scripted conversation.
Here's an example of some working server & client code to illustrate how you could perform this conversation:
Code to kick off both client & server:
static void Main()
{
var server = Task.Factory.StartNew(() => RunServer());
var client = Task.Factory.StartNew(() => RunClient());
Task.WaitAll(server, client);
Console.WriteLine("Done");
}
Client code:
static void RunClient()
{
using (var pipeClient = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut))
{
Console.WriteLine("Client is waiting to connect");
if(!pipeClient.IsConnected){pipeClient.Connect();}
Console.WriteLine("Client is connected");
using (var reader = new StreamReader(pipeClient))
{
using (var writer = new StreamWriter(pipeClient))
{
var running = true;
while(running)
{
Console.WriteLine("Client is waiting for input");
var message = reader.ReadLine();
if (message != null)
{
Console.WriteLine("Client: Recieved from server {0}", message);
switch (message)
{
case "Do you accept (y/n):":
writer.WriteLine("y");
writer.WriteLine("quit");
writer.Flush();
break;
case "quit":
running = false;
break;
}
}
}
}
}
}
Console.WriteLine("Client Quits");
}
Server code:
static void RunServer()
{
using (var pipeServer = new NamedPipeServerStream("TestPipe", PipeDirection.InOut))
{
using (var reader = new StreamReader(pipeServer))
{
using (var writer = new StreamWriter(pipeServer))
{
var running = true;
Console.WriteLine("Server is waiting for a client");
pipeServer.WaitForConnection();
Console.WriteLine("Server has connection from client");
Console.WriteLine("Server: Saying Hi");
writer.WriteLine("Hello!");
Console.WriteLine("Server: Prompting for Input");
writer.WriteLine("Do you accept (y/n):");
writer.Flush();
while(running)
{
pipeServer.WaitForPipeDrain();
var message = reader.ReadLine();
Console.WriteLine("Server: Recieved from client {0}", message);
if (message.Equals("quit"))
{
writer.WriteLine("quit");
running = false;
}
}
}
}
}
Console.WriteLine("Server Quits");
}
Update
Amended code to read characters rather than lines; so we don't have to wait for a line break before seeing the server's messages.
//using System.Threading.Tasks;
//using System.IO.Pipes;
static void Main()
{
var server = Task.Factory.StartNew(() => RunServer());
var client = Task.Factory.StartNew(() => RunClient());
Task.WaitAll(server, client);
Console.WriteLine("Done");
}
static void RunClient()
{
using (var pipeClient = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut))
{
Console.WriteLine("Client is waiting to connect");
if(!pipeClient.IsConnected){pipeClient.Connect();}
Console.WriteLine("Client is connected");
using (var reader = new StreamReader(pipeClient))
{
using (var writer = new StreamWriter(pipeClient))
{
var message = string.Empty;
var running = true;
while(running)
{
Console.WriteLine("Client is waiting for input");
var chr = reader.Read();
if (chr >= 32)
{
message = message + (char)chr;
Console.WriteLine("Client: Recieved from server {0}", message);
switch (message)
{
case "Do you accept (y/n):":
writer.WriteLine("y");
writer.WriteLine("quit");
writer.Flush();
break;
case "quit":
running = false;
break;
}
}
else {
message = string.Empty;
Console.WriteLine("Client: New Line Received from Server");
}
}
}
}
}
Console.WriteLine("Client Quits");
}
static void RunServer()
{
using (var pipeServer = new NamedPipeServerStream("TestPipe", PipeDirection.InOut))
{
using (var reader = new StreamReader(pipeServer))
{
using (var writer = new StreamWriter(pipeServer))
{
var running = true;
Console.WriteLine("Server is waiting for a client");
pipeServer.WaitForConnection();
Console.WriteLine("Server has connection from client");
Console.WriteLine("Server: Saying Hi");
writer.WriteLine("Hello!");
Console.WriteLine("Server: Prompting for Input");
writer.Write("Do you accept (y/n):"); //NB: This is a write, not a write line!
writer.Flush();
while(running)
{
pipeServer.WaitForPipeDrain();
var message = reader.ReadLine();
Console.WriteLine("Server: Recieved from client {0}", message);
switch (message)
{
case "quit":
writer.WriteLine("quit");
running = false;
break;
default:
writer.WriteLine("");
break;
}
}
}
}
}
Console.WriteLine("Server Quits");
}
So this is what your code should look like:
int charAsInt;
var line = string.Empty;
while(((charAsInt = reader.Read()) != -1)) {
if (charAsInt >= 32) { //is a displayable character
line = line + (char)charAsInt;
//your code to handle the lines
if(line.Contains("Hello!")) {
writer.WriteLine("1.2.3.4"); // input for the next prompt
} else if(line.Contains("Text1") {
writer.WriteLine("2.3.4.5"); // input for next prompt of Text2
}
writer.Flush();
//writer.WaitForPipeDrain();
} else { //is a control character
if (charAsInt == 10 || charAsInt == 13) { //carriage return or line feed; i.e. end of line
if (line.Length > 0) {
Debug.WriteLine("Last line read was {0}", line); //just so you can see info as it comes from the server
line = string.Empty;
}
}
}
}

Wait until a message has been received and pass the message body using C# RabbitMQ

I want to read a message from a queue, and once available wants to send the byte[] outside the consumer class.
public byte[] Receive()
{
if (messagingAdapter == null)
return default(byte[]);
byte[] messageBody = null;
var channel = messagingAdapter.GetChannel();
channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
using (var subscription = new Subscription(channel, containerName, false))
{
while (channel.IsOpen)
{
var success = subscription.Next(5000, out BasicDeliverEventArgs eventArgs);
if (success == false) continue;
messageBody = eventArgs.Body;
channel.BasicAck(eventArgs.DeliveryTag, false);
}
}
return messageBody;
}
In the above code, there are two issues (can be more).
1) Even after writing prefetchCount = 1, it still reads all the messages.
2) Ever after waiting for 5 seconds, I never get a success and I'm not able to send the body to outside.
I have written one more code, which does the same thing but in the post itself, it was written that it is not recommended way of doing.
Sample Code:
using (var signal = new ManualResetEvent(false))
{
var consumer = new EventingBasicConsumer(channel);
consumer.Received +=
(sender, args) =>
{
messageBody = args.Body;
signal.Set();
};
//// start consuming
channel.BasicConsume(containerName, true, consumer);
// wait until message is received or timeout reached
bool timeout = !signal.WaitOne(TimeSpan.FromSeconds(10));
// cancel subscription
channel.BasicCancel(consumer.ConsumerTag);
if (timeout)
{
// timeout reached - do what you need in this case
throw new Exception("timeout");
}
return messageBody;
// at this point messageBody is received
}
Try reading with channel.BasicGet instead, something like this:
private byte[] ReadRabbitMsg(IModel channel, string queue)
{
if (channel.MessageCount(queue) == 0) return null;
BasicGetResult result = channel.BasicGet(queue, true);
if (result == null) return null;
else
{
IBasicProperties props = result.BasicProperties;
byte[] buff = result.Body;
}
}

Categories

Resources