Exchanging messages between two C# processes - c#

I have two console apps written with C#. I'm trying to exchange messages between them. In an attempt to do this, I'm using non-persisted memory-mapped files. In my scenario, one console app is the parent and the other is the child. Sometimes, the parent will send a message to the child. Other times, the child will send a message to the parent.
I can't figure out how to do this though. It's like each process is either listening or speaking. It's not actively doing both. At this time, I'm trying to exchange messages between the two processes using a struct that's defined as this:
public struct Message
{
public string Source { get; set; }
public string Text { get; set; }
}
My parent console app has a method that looks like this:
private void SendMessageToChild(string text, int childHandle)
{
Console.WriteLine("Sending message to child...");
var messageChannelFileName = childHandle.ToString() + ".msgs";
using (var messageChannelFile = MemoryMappedFile.CreateOrOpen(messageChannelFileName, 10240))
{
using (var memoryMappedAccessor = messageChannelFile.CreateViewAccessor())
{
var message = new Message();
message.Text = text;
message.Source = "Parent";
memoryMappedAccessor.Write<Message>(0, ref message);
}
}
Console.ReadKey(); // This is to keep the memory mapped file open for the child to be able to read it
Console.WriteLine("Successfully sent message to child.");
}
My child console app (process) has a method that looks like this:
private void StartListening()
{
Task.Run(() =>
{
var messageChannelFileName = Process.GetCurrentProcess().Id + ".msgs";
using (var messageChannelFile = MemoryMappedFile.OpenExisting(messageChannelFileName, MemoryMappedFileRights.Read))
{
var message = new Message();
using (var messageAccessor = messageChannelFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read))
{
messageAccessor.Read<Message>(0, out message);
Console.WriteLine(message.Text);
}
}
Console.ReadKey(); // This is to keep the memory mapped file
});
}
This approach isn't working. I never see the message printed to the console window. At the same time, I do not see a way to send messages back-and-forth. In my opinion, the Console.ReadKey required in both sides locks the file.
Am I misunderstanding something? Am I using the wrong thing to exchange messages between two processes? I know I can't use Pipes for my scenario, which is why I went with memory mapped files.

Its really easy to communicate between 2 processes
For example Parent process do that :
// create EventWaitHandle, MemoryMapped and accessor
ewh = new EventWaitHandle(false, EventResetMode.AutoReset, "ewhFreePIE");
memory = MemoryMappedFile.CreateOrOpen("hookFreePIE", 68, MemoryMappedFileAccess.ReadWrite);
accessor = memory.CreateViewAccessor();
:
:
// Send message with accessor.write
ewh.Set();//say to other process, there is something to read
Example of Child Process:
memory = MemoryMappedFile.CreateOrOpen("hookFreePIE", 68, MemoryMappedFileAccess.ReadWrite);
accessor = memory.CreateViewAccessor();
ewh = EventWaitHandle.OpenExisting("ewhFreePIE");
:
:
// sample of loop
public void StartLoop()
{
while (running)
{
ewh.WaitOne();// wait Set() of another or same process
if (cmdtostop) //you could create cmdstop inside memorymapped file (set first byte to 1 for example
{
running = false;
}
else
{
//do something with data , using accessor.Read
}
}
if you want child send to parent you create another EventWaithandle and do the same thing from child to Parent
Dont forget to dispose resource when process finish

Related

BLE ValueChanged stops firing in C# app

I'm running Windows version 10.0.16299.0, and building on Visual Studio C# 2017. I can successfully connect to an unpaired BLE device from a Windows Forms app, and get ValueChanged events (1 per second), but not for long. I usually stop receiving those events in 40 seconds or less - usually less.
I realize this is likely a dispose/GC issue, but I don't see how. The device, service, characteristics, and descriptors are all stored as member variables in the main form and should not get collected:
public partial class Form1 : Form
{
private BluetoothLEDevice _device;
private List<GattDeviceService> _services;
private List<GattDescriptor> _descriptors = new List<GattDescriptor>();
private List<GattCharacteristic> _characteristics = new List<GattCharacteristic>();
private async void button1_Click(object sender, EventArgs e)
{
_device = await BluetoothLEDevice.FromIdAsync("BluetoothLE#BluetoothLE00:xx:xx:xx:xx:xx:xx:xx:xx:xx");
var services = await _device.GetGattServicesAsync();
foreach (var service in services.Services)
{
var chars = await service.GetCharacteristicsAsync();
foreach (var ch in chars.Characteristics)
{
var descriptors = await ch.GetDescriptorsAsync();
foreach (var desc in descriptors.Descriptors)
{
if (desc.AttributeHandle == 15 || desc.AttributeHandle == 26)
{
_services.Add(service);
_descriptors.Add(desc);
_characteristics.Add(ch);
var writer = new DataWriter();
writer.WriteBytes(new byte[] { 1, 0 });
var buf = writer.DetachBuffer();
await desc.WriteValueAsync(buf);
}
ch.ValueChanged += ChOnValueChanged;
}
}
}
}
In my sample, I click a button to establish a connection and subscribe to events. Before you say that writing to the descriptor is not how you would do it - I know. The device uses non-standard descriptor IDs which is why I must write to them directly.
Note that everything works, including the writes - I get no errors. It's just that the ValueChanged event is no longer fired after a short duration, and I can't figure out what else I must "cache" in order to prevent objects from being disposed, assuming that's what the problem is.
The problem is that because of the nested for each iterations you attach the characteristic_changed_event to multiple characteristics. That leads to unwanted behaviour.
The best way is to select the service that contains the wanted characteristic by UUID, then select the characteristic by UUID from that service.
If you insist on filtering by the wanted descriptor attribute handle,
finish all the "for each-es" before attaching the characteristic_changed_event.
The characteristic to attach to is probably first in _characteristics list.

Can't get NetMQ pub-sub pattern to work with ReceiveReady

I'm trying my hands on NetMQ (3.3.3.4) and creating a pub-sub pattern.
I want a host/server to listen to all incoming data on one port (9000) and forward the data to all clients/subscribers on another port (9001).
The clients will then send data on 9000 and receive all messages sent (by whomever) on 9001.
Following the documentation I created something like the code below, but I can't get it to work. Mainly, I believe, because ReceiveReady is never called!
How I believe it should work:
client.Publish should cause the first line in host.SubscriberSocket_ReceiveReady to unblock and pass the data along to the other socket
When data has been passed along it should appear in the infinite running Task in the client
Results:
Breakpoints on // This line is never reached are never reached
There are no exceptions anywhere.
Switching the ports on the host so that publish = 9000 and subscribe = 9001 has no effect
Windows Firewall is turned off, so there should not be any blocking
It makes no difference if I'm putting the address into PublisherSocket constructor, or if I'm using _publisherSocket.Bind(address) in Host or _publisherSocket.Connect(address) in Client
What am I doing wrong?
Host
public class MyNetMQHost {
private NetMQSocket _publishSocket;
private NetMQSocket _subscribeSocket;
private NetMQPoller _poller;
public MyNetMQHost(string publishAddress = "#tcp://localhost:9001", string subscribeAddress = "#tcp://localhost:9000") {
Task.Factory.StartNew(() => {
using (_publishSocket = new PublisherSocket(publishAddress))
using (_subscribeSocket = new SubscriberSocket(subscribeAddress))
using (_poller = new NetMQPoller { _publishSocket, _subscribeSocket }) {
_subscriberSocket.ReceiveReady += SubscriberSocket_ReceiveReady;
_poller.Run();
}
});
}
private void SubscriberSocket_ReceiveReady(object sender, NetMQSocketEventArgs e) {
var data = e.Socket.ReceiveMultipartBytes(); // This line is never reached
_publishSocket.SendMultipartBytes(data);
}
}
Client
public class MyNetMQClient {
private readonly NetMQSocket _publishSocket;
private readonly NetMQSocket _subscribeSocket;
public MyNetMQClient(string publishAddress = ">tcp://localhost:9000", string subscribeAddress = ">tcp://localhost:9001") {
_publishSocket = new PublisherSocket(publishAddress);
_subscribeSocket = new SubscriberSocket(subscribeAddress);
Task.Factory.StartNew(() => {
while (true) {
byte[] frameBytes = _subscribeSocket.ReceiveFrameBytes();
int one = 1; // This line is never reached
}
});
}
public void Publish(byte[] data) {
_publishSocket.SendFrame(data);
}
}
Tester
public class Tester {
public void MyTester() {
MyNetMQHost host = new MyNetMQHost();
MyNetMQClient client = new MyNetMQClient();
client.Publish(Encoding.Unicode.GetBytes("Hello world!");
}
}
Both your broker and client never call suscribe.
On the broker call suscriber.Subscribe("") to subscribe for all. On your client subscribe to what ever you want.
In your broker you should actually use XSubscriber and XPublisher to move susvriptions around. That way you dont need the subscribe all. You can use Proxy class for that.

C# all pipe instances are busy

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

SignalR notification system

This is my first time playing around with SignalR. I am trying to build a notification system where the server checks at regular intervals to see if there is something (query database) to broadcast and if there is then it broadcasts it to all the clients.
I came across this post on Stackoverflow and was wondering if modifying the code to make a DB call at a particular interval was indeed the right way to do it. If not is there a better way to do it?
I did see a lot of Notification related questions posted here but none with any code in it. Hence this post.
This is the exact code that I am using:
public class NotificationHub : Hub
{
public void Start()
{
Thread thread = new Thread(Notify);
thread.Start();
}
public void Notify()
{
List<CDCNotification> notifications = new List<CDCNotification>();
while (true)
{
notifications.Clear();
notifications.Add(new CDCNotification()
{
Server = "Server A", Application = "Some App",
Message = "This is a long ass message and amesaadfasd asdf message",
ImgURL = "../Content/Images/accept-icon.png"
});
Clients.shownotification(notifications);
Thread.Sleep(20000);
}
}
}
I am already seeing some weird behaviour where the notifications come more often than they are supposed to. Even though I am supposed to get it every 20s I get it around 4-5 secs and I get multiple messages.
Here is my client:
var notifier = $.connection.notificationHub;
notifier.shownotification = function (data) {
$.each(data, function (i, sample) {
var output = Mustache.render("<img class='pull-left' src='{{ImgURL}}'/> <div><strong>{{Application}}</strong></div><em>{{Server}}</em> <p>{{Message}}</p>", sample);
$.sticky(output);
});
};
$.connection.hub.start(function () { notifier.start(); });
Couple of notes:
As soon as a second client connects to your server there will be 2 threads sending the notifications, therefore if you ave more than one client you will have intervals smaller than 20s
Handling thread manually within ASP.NET is considered bad practice, you should avoid this if possible
In general this smells a lot like polling which is kind of the thing SignalR lets you get rid of since you don't need to signal the server/client
In order to solve this you need todo something like this (again, threads in a web application are generally not a good idea):
public class NotificationHub : Hub
{
public static bool initialized = false;
public static object initLock = new object();
public void Start()
{
if(initialized)
return;
lock(initLock)
{
if(initialized)
return;
Thread thread = new Thread(Notify);
thread.Start();
initialized = true;
}
}
public void Notify()
{
List<CDCNotification> notifications = new List<CDCNotification>();
while (true)
{
notifications.Clear();
notifications.Add(new CDCNotification() { Server = "Server A", Application = "Some App", Message = "This is a long ass message and amesaadfasd asdf message", ImgURL = "../Content/Images/accept-icon.png" });
Clients.shownotification(notifications);
Thread.Sleep(20000);
}
}
}
The static initialized flag prevents multiple threads from being created. The locking around it is to ensure that the flag is only set once.
I am working on the same task over here. Instead of continuously checking the database, I created my own events and listener, where an event is RAISED when a NOTIFICATION IS ADDED :) What do you think about that?

Clickonce application and file handler behavior

I have a clickonce application, and I have set up several file handlers for this application (for the sake of this example, I want to handle files with either the .aaa or .bbb extensions).
If I select a single file with one of these extensions, my application starts up as expected, everything is good. But if I select multiple files and open them (either by hitting Enter or by right clicking and selecting Open), then multiple instances of my aopplication are started up - one instance per file that was selected.
This is not the behavior I expected, I want just one instance to start with multiple file entries in the AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData. Can this be achieved, or is my expectation incorrect?
Edit:
Just to elaborate: we have followed the single instance approach as mentioned by #Matthias, the first instance to start up creates a named server pipe. Subsequent instances then start up, detect that they are secondary, communicate their command line arguments (filename) through to the main instance via the named pipe, then quit. The main instance receives the filename via the named pipe, and does its thing (starts up a file import wizard).
The issue comes when a user selects several files (i.e. 5 files), then selects to open those files in the application. Instead of getting one secondary instance starting with 5 file names supplied on the command line, I'm getting 5 secondary instances of the application starting, each with a single filename on the command line. Each of these then creates a client named pipe and communicates that filename to the main instance - so the server named pipe receives 5 separate messages.
Follow up thoughts:
after chatting about this it occurs to me that maybe this is just the way registered file handlers work, maybe it is not related to clickonce. Maybe the solution is for the server named pipe to pause after receiving each message and to attempt to queue messages before actioning them?
You can achieve this by implementing a single instance application. If the application is already running (second call), you can use named pipes to inform the application (first call) of a file open event.
EDIT
Found a code snippet from an earlier project. I want to underline that the code definitely needs improvements, but it should be a good point where you can start from.
In your static main:
const string pipeName = "auDeo.Server";
var ownCmd = string.Join(" ", args);
try
{
using (var ipc = new IPC(pipeName))
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new ServerForm();
ipc.MessageReceived += m =>
{
var remoteCmd = Encoding.UTF8.GetString(m);
form.Invoke(remoteCmd);
};
if (!string.IsNullOrEmpty(ownCmd))
form.Invoke(ownCmd);
Application.Run(form);
}
}
catch (Exception)
{
//MessageBox.Show(e.ToString());
if (string.IsNullOrEmpty(ownCmd))
return;
var msg = Encoding.UTF8.GetBytes(ownCmd);
IPC.SendMessage(pipeName, msg);
}
The IPC class:
public class IPC : IDisposable
{
public IPC(string pipeName)
{
Stream = new NamedPipeServerStream(pipeName,
PipeDirection.InOut,
1,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous);
AsyncCallback callback = null;
callback = delegate(IAsyncResult ar)
{
try
{
Stream.EndWaitForConnection(ar);
}
catch (ObjectDisposedException)
{
return;
}
var buffer = new byte[2000];
var length = Stream.Read(buffer, 0, buffer.Length);
var message = new byte[length];
Array.Copy(buffer, message, length);
if (MessageReceived != null)
MessageReceived(message);
Stream.Disconnect();
// ReSharper disable AccessToModifiedClosure
Stream.BeginWaitForConnection(callback, null);
// ReSharper restore AccessToModifiedClosure
};
Stream.BeginWaitForConnection(callback, null);
}
private NamedPipeServerStream Stream
{
get;
set;
}
#region IDisposable Members
public void Dispose()
{
if (Stream != null)
Stream.Dispose();
}
#endregion
public static void SendMessage(string pipeName, byte[] message)
{
using (var client = new NamedPipeClientStream(".", pipeName))
{
client.Connect();
client.Write(message, 0, message.Length);
client.Close();
}
}
~IPC()
{
Dispose();
}
public event MessageHandler MessageReceived;
}
The answer to the problem was to have a small delay at the server end of the pipe. In summary:
the first started instance of the app is the owner of the server end of the pipe, subsequent instances of the app are a client
When receiving a message from a client, a timer was started, if the timer was already started then it was reset. The passed file name is added to a list.
The timer delay was set to 2 seconds, once the tick event occurred (so it had been 2 seconds since the last client communication) the single instance server would take the appropriate action with the list of file names
This is not the behavior I expected, I want just one instance to start with multiple file entries in the AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData. Can this be achieved, or is my expectation incorrect?
My expectation was incorrect - you can only pass through a single file name to a registered file handler, each file name starts a separate instance of the handler.

Categories