I'm trying to implement the NetMQ Pub/Sub Model, but the Subscriber is not receiving any messages. What possibly is wrong here?
private static void ServerTask()
{
using (var context = NetMQContext.Create())
{
using (var socket = context.CreateSubscriberSocket())
{
socket.Bind("tcp://10.120.19.109:5000");
socket.Subscribe(string.Empty);
while (true)
{
Thread.Sleep(100);
string receivedMessage = socket.ReceiveString();
Console.WriteLine("Received: " + receivedMessage);
}
}
}
}
public static void ClientTask()
{
using (NetMQContext ctx = NetMQContext.Create())
{
using (var socket = ctx.CreatePublisherSocket())
{
socket.Connect("tcp://10.120.19.109:5000");
string obj = "hi";
socket.Send(obj);
}
}
}
Both are in different apps.
If you are new to NetMQ I suggest reading the zeromq guide http://zguide.zeromq.org/page:all.
Bottom line is that you are sending the message before the subscriber sent the subscription.
Pubsub in zeromq and NetMQ is like radio, you will only get messages from the moment you start listen.
To simple way to do it (not a real life solution) is to sleep for some time after the connect.
For real life solution I need to understand what are you trying to achieve
issue is like
using (NetMQContext ctx = NetMQContext.Create())
{
using (var publisher = ctx.CreatePushSocket())
{
publisher.Bind("tcp://localhost:5000");
int i = 0;
while (true)
{
try
{
publisher.Send(i.ToString(), dontWait:true);
Console.WriteLine(i.ToString());
}
catch (Exception e)
{
}
finally
{
i++;
}
}
}
Now , this code works. But if I move my while(true) loop outside. and call this code from some other function Which forces push socket and context to be created as new everytime.. this doesnot work.
Related
public static async Task DoMessage()
{
const int numberOfMessages = 10;
queueClient = new QueueClient(ConnectionString, QueueName);
await SendMessageAsync(numberOfMessages);
await queueClient.CloseAsync();
}
private static async Task SendMessageAsync(int numOfMessages)
{
try
{
for (var i = 0; i < numOfMessages; i++)
{
var messageBody = $"Message {i}";
var message = new Message(Encoding.UTF8.GetBytes(messageBody));
message.SessionId = i.ToString();
await queueClient.SendAsync(message);
}
}
catch (Exception e)
{
}
}
This is my sample code to send message to the service bus queue with session id.
My question is if I call DoMessage function 2 times: Let's name it as MessageSet1 and MessageSet2, respectively. Will the MessageSet2 be received and processed by the received azure function who dealing with the receiving ends of the message.
I want to handle in order like MessageSet1 then the MessageSet2 and never handle with MessageSet2 unless MessageSet1 finished.
There are a couple of issues with what you're doing.
First, Azure Functions do not currently support sessions. There's an issue for that you can track.
Second, the sessions you're creating are off. A session should be applied on a set of messages using the same SessionId. Meaning your for loop should be assigning the same SessionId to all the messages in the set. Something like this:
private static async Task SendMessageAsync(int numOfMessages, string sessionID)
{
try
{
var tasks = new List<Task>();
for (var i = 0; i < numOfMessages; i++)
{
var messageBody = $"Message {i}";
var message = new Message(Encoding.UTF8.GetBytes(messageBody));
message.SessionId = sessionId;
tasks.Add(queueClient.SendAsync(message));
}
await Task.WhenAll(tasks).ConfigureAwait(false);
}
catch (Exception e)
{
// handle exception
}
}
For ordered messages using Sessions, see documentation here.
I am developing a quartz.net job which runs every 1 hour. It executes the following method. I am calling a webapi inside a for loop. I want to make sure i return from the GetChangedScripts() method only after all thread is complete? How to do this or have i done it right?
Job
public void Execute(IJobExecutionContext context)
{
try
{
var scripts = _scriptService.GetScripts().GetAwaiter().GetResult();
}
catch (Exception ex)
{
_logProvider.Error("Error while executing Script Changed Notification job : " + ex);
}
}
Service method:
public async Task<IEnumerable<ChangedScriptsByChannel>> GetScripts()
{
var result = new List<ChangedScriptsByChannel>();
var currentTime = _systemClock.CurrentTime;
var channelsToProcess = _lastRunReader.GetChannelsToProcess().ToList();
if (!channelsToProcess.Any()) return result;
foreach (var channel in channelsToProcess)
{
var changedScripts = await _scriptRepository.GetChangedScriptAsync(queryString);
if (changedScriptsList.Any())
{
result.Add(new ChangedScriptsByChannel()
{
ChannelCode = channel.ChannelCode,
ChangedScripts = changedScriptsList
});
}
}
return result;
}
As of 8 days ago there was a formal announcement from the Quartz.NET team stating that the latest version, 3.0 Alpha 1 has full support for async and await. I would suggest upgrading to that if at all possible. This would help your approach in that you'd not have to do the .GetAwaiter().GetResult() -- which is typically a code smell.
How can I use await in a for loop?
Did you mean a foreach loop, if so you're already doing that. If not the change isn't anything earth-shattering.
for (int i = 0; i < channelsToProcess.Count; ++ i)
{
var changedScripts =
await _scriptRepository.GetChangedScriptAsync(queryString);
if (changedScriptsList.Any())
{
var channel = channelsToProcess[i];
result.Add(new ChangedScriptsByChannel()
{
ChannelCode = channel.ChannelCode,
ChangedScripts = changedScriptsList
});
}
}
Doing these in either a for or foreach loop though is doing so in a serialized fashion. Another approach would be to use Linq and .Select to map out the desired tasks -- and then utilize Task.WhenAll.
I have a long running PostgreSQL function. For simplicity, something like this:
CREATE FUNCTION pg_function()
RETURNS void
AS
$$
BEGIN
PERFORM pg_notify('channel1', 'pg_function() started.');
PERFORM pg_sleep(5);------PERFORM task1();-----------------------------------------
PERFORM pg_notify('channel1', 'Task1 payload.');
PERFORM pg_sleep(5);------PERFORM task2();-----------------------------------------
PERFORM pg_notify('channel1', 'Task2 payload.');
PERFORM pg_sleep(5);------PERFORM task3();-----------------------------------------
PERFORM pg_notify('channel1', 'Task3 payload.');
PERFORM pg_notify('channel1', 'pg_function() completed.');
END;
$$
LANGUAGE "plpgsql";
On C#, I have:
public bool listening;
public void PgFunction()
{
this.listening = true;
ThreadStart listenerStart = delegate
{
using (NpgsqlConnection connection = new NpgsqlConnection(this.connectionString))
{
connection.Open();
connection.Notification += Listen;
using (NpgsqlCommand listenChannel1 = new NpgsqlCommand("LISTEN channel1;", connection))
{
listenChannel1.ExecuteNonQuery();
}
while (this.listening)
{
using (NpgsqlCommand pollingCommand = new NpgsqlCommand("SELECT 0;", connection))
{
pollingCommand.ExecuteNonQuery();
}
Thread.Sleep(5000);
}
}
};
Thread listenerThread = new Thread(listenerStart) { IsBackground = false };
listenerThread.Start();
ThreadStart pgFunctionThreadStart = () => ExecuteNonQuery(new NpgsqlCommand("SELECT pg_function();"));
pgFunctionThreadStart += () =>
{
Thread.Sleep(5000);
this.listening = false;
};
Thread pgFunctionThread = new Thread(pgFunctionThreadStart) { IsBackground = true };
pgFunctionThread.Start();
}
private void Listen(object sender, NpgsqlNotificationEventArgs e)
{
string payload = e.AdditionalInformation;
//SignalR stuff here
}
When I run the program debugging, this code works okay. But when it is tested on IIS server or browsed with Visual Studio 2013 integrated IIS, the application crashes. Since I have very little knowledge of tasks and threads in C#, I would like to know what I am doing wrong here? Please advise.
Edit
Upon debugging it again, I came with a NpgsqlException, which happens to happen once in a while:
Additional information: Cannot write to a BufferedStream while the read buffer is not empty if
the underlying stream is not seekable. Ensure that the stream underlying this BufferedStream
can seek or avoid interleaving read and write operations on this BufferedStream.
I am working on a Windows Universal App. I Want to get the Data from a Bluetooth Device to the Windows Phone. I am Using the Concept of RFCommCommunicationTrigger for this Purpose.
Here's the code Snippet I am Using
var rfTrigger = new RfcommConnectionTrigger();
// Specify what the service ID is
rfTrigger.InboundConnection.LocalServiceId = RfcommServiceId.FromUuid(new Guid("<some_base_guid>"));
//Register RFComm trigger
var rfReg = RegisterTaskOnce(
"HWRFCommTrigger",
"BackgroundLibrary.RFBackgroundTask",
rfTrigger, null
);
SetCompletedOnce(rfReg, OnTaskCompleted);
Here the Function of RegisterTaskOnce
static private IBackgroundTaskRegistration RegisterTaskOnce(string taskName, string entryPoint, IBackgroundTrigger trigger, params IBackgroundCondition[] conditions)
{
// Validate
if (string.IsNullOrEmpty(taskName)) throw new ArgumentException("taskName");
if (string.IsNullOrEmpty(entryPoint)) throw new ArgumentException("entryPoint");
if (trigger == null) throw new ArgumentNullException("trigger");
// Look to see if the name is already registered
var existingReg = (from reg in BackgroundTaskRegistration.AllTasks
where reg.Value.Name == taskName
select reg.Value).FirstOrDefault();
Debug.WriteLine("Background task "+ taskName+" is already running in the Background");
// If already registered, just return the existing registration
if (existingReg != null)
{
return existingReg;
}
// Create the builder
var builder = new BackgroundTaskBuilder();
builder.TaskEntryPoint = entryPoint;
builder.Name = taskName;
builder.SetTrigger(trigger);
// Conditions?
if (conditions != null)
{
foreach (var condition in conditions)
{
builder.AddCondition(condition);
}
}
// Register
return builder.Register();
}
Here's the code for SetCompletedOnce this will add a Handler only once
static private void SetCompletedOnce(IBackgroundTaskRegistration reg, BackgroundTaskCompletedEventHandler handler)
{
// Validate
if (reg == null) throw new ArgumentNullException("reg");
if (handler == null) throw new ArgumentNullException("handler");
// Unsubscribe in case already subscribed
reg.Completed -= handler;
// Subscribe
reg.Completed += handler;
}
I have also Written the BackgroundLibrary.RFBackgroundTask.cs
public sealed class RFBackgroundTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
try
{
Debug.WriteLine(taskInstance.TriggerDetails.GetType());
taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
Debug.WriteLine("RFComm Task Running");
Debug.WriteLine(taskInstance.TriggerDetails.GetType().ToString());
}
catch (System.Exception e)
{
Debug.WriteLine("RFComm Task Error: {0}", e.Message);
}
deferral.Complete();
}
}
The Run Method is Invoked Every Time The Device tries to Open the Connection.
The type of the Trigger that is obtained (the type I am debugging in the run method of the RFBackgroundTask.cs) is printed as
Windows.Devices.Bluetooth.Background.RfcommConnectionTriggerDetails
But I am Unable use that because I dont have this Class in the BackgroundLibrary project.
The Documentation says that this Provides information about the Bluetooth device that caused this trigger to fire.
It has Variables like Socket,RemoteDevice etc.
I think I am Missing something very simple
Can you please help me out .
Once your background task is launched, simply cast the TriggerDetails object to an RfcommConnectionTriggerDetails object:
public sealed class RFBackgroundTask : IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
try
{
taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
RfcommConnectionTriggerDetails details = (RfcommConnectionTriggerDetails)taskInstance.TriggerDetails;
StreamSocket = details.Socket; // Rfcomm Socket
// Access other properties...
}
catch (System.Exception e)
{
Debug.WriteLine("RFComm Task Error: {0}", e.Message);
}
deferral.Complete();
}
}
Sample code here
public override void Run()
{
while (true)
{
IAsyncResult result = CUDClient.BeginReceive(TimeSpan.FromSeconds(10), OnMessageReceive, CUDClient);
Thread.Sleep(10000);
}
}
I have tested this Azure worker role. I kept 100 messages in the Service bus Queue. It's doing entities updates as a operation(Entity framework). It took 15 minutes to process all the queues and looks like taking longer time. Any suggestion to improve this?
Thanks in Advance
Actually Service Bus is very fast enough in my experience. What wrong with you is "Thread.Sleep(10000)";
Sleeping 10 sec for each message.
For 100 messages 100*10 = 10000 seconds = 16.67 minutes
So this is a problem for the delay...
Solution:
Dont use Thread.Sleep(10000); (Its not suitable for BeginReceive, only suitable for Receive)
public override void Run() //This should not be a Thread...If its a thread then your thread will terminate after receiving your first message
{
IAsyncResult result = CUDClient.BeginReceive(**TimeSpan.MaxValue**, OnMessageReceive, CUDClient);
}
//Function OnMessageReceive
{
//Process the Message
**IAsyncResult result = CUDClient.BeginReceive(TimeSpan.MaxValue, OnMessageReceive, CUDClient);**
}
using TimeSpan.MaxValue your connection to the SB will be preserved for longtime. so no frequent null message(less cost)...
Try using XecMe Parallel task for processing the message reading.
XecMe # xecme.codeplex.com
Try this one...
//Somefunction
IAsyncResult result = CUDClient.BeginReceive(OnMessageReceive, CUDClient);
while (true)
Thread.Sleep(1000); //In case you are using thread
//Somefunction End
public static void OnMessageReceive(IAsyncResult result)
{
CUDClient.BeginReceive(OnMessageReceive, CUDClient);
SubscriptionClient queueClient = (SubscriptionClient)result.AsyncState;
IBusinessLogicProvider Obj;
try
{
//Receive the message with the EndReceive call
BrokeredMessage receivedmsg = queueClient.EndReceive(result);
//receivedmsg = CUDClient.Receive();
if (receivedmsg != null)
{
switch (receivedmsg.ContentType)
{
case "Project":
Obj = new ProjectsBL();
Obj.HandleMessage(receivedmsg);
receivedmsg.BeginComplete(OnMessageComplete, receivedmsg);
break;
}
}
}
}
I tried this.
while (true)
{
//read all topic messages in sequential way....
IAsyncResult result = CUDClient.BeginReceive(OnMessageReceive, CUDClient);
Thread.Sleep(1000);
}
public static void OnMessageReceive(IAsyncResult result)
{
SubscriptionClient queueClient = (SubscriptionClient)result.AsyncState;
IBusinessLogicProvider Obj;
try
{
//Receive the message with the EndReceive call
BrokeredMessage receivedmsg = queueClient.EndReceive(result);
//receivedmsg = CUDClient.Receive();
if (receivedmsg != null)
{
switch (receivedmsg.ContentType)
{
case "Project":
Obj = new ProjectsBL();
Obj.HandleMessage(receivedmsg);
receivedmsg.BeginComplete(OnMessageComplete, receivedmsg);
break;
}
}
}
}
It processed all the 100 messages in 1 minute(00:01:02) . A lot better than previous one.