DarioSantarelli.Blog(this);

Archive for the ‘Compact Framework’ Category

[.NET Compact Framework] Working with Point-to-Point Message Queues

Posted by dariosantarelli on June 11, 2011


While working on a project of mine, I’ve got to face an interprocess communication (IPC) on a Windows CE device. In my scenario, the device vendor uses the Message Queue Point-To-Point infrastructure so that native processes can communicate with managed processes through IPC. On other Windows platforms, IPC can be achieved through named pipes (native) or remoting (managed), but none of these options are available to Windows CE. Point-to-point represents a little-known IPC mechanism that is efficient, flexible, and unique to Windows CE version 4.0 and later. Moreover it can interact with the operating system, for example, for getting power information.

If you don’t know this feature of Windows CE, first of all you should read this MSDN article:

Point-to-Point Message Queues with the .NET Compact Framework.

After analyzing the managed wrapper proposed by the article, I’ve started to refactor the source code in order to make it more suitable for my needs. So, I’d like to share my design and implementation :).

Let’s explain some key concepts:

  • A message queue can be addressed by a name or, generally, by an handle. The handle is the only data you can refer to if the queue has no name (NULL). Note that the empty string is considered a valid, non-null name.
  • A message queue can be read-only or write-only: it means that a process can get an handle to a message queue just for reading or writing messages. If you want to read from and write to the same queue, you should create two handles pointing to the same queue.
  • Message queues are FIFO. Writers can write messages in a queue until it’s full and readers can read messages from a queue until it’s empty. When a reader process invokes a read operation on a message queue, the first unread message is removed from the queue and delivered to the reading process.

As you can see in the class diagram above, I’ve defined an abstract MessageQueue class which holds the queue info ( e.g. the max length, the max message length, the current readers/writers count and so on… ) and exposes a generic factory method for creating concrete implementations.

public static T Create<T>(string name) where T : MessageQueue
public static T Create<T>(string name, int length) where T : MessageQueue
public static T Create<T>(string name, int length, int maxMessageLength) where T : MessageQueue

Let’s have a look to them:

WriteOnlyMessageQueue

It’s a concrete class for writing messages in a queue. The class exposes some overloads of the Write() method in order to write a message in a queue and choose whether to block the calling thread until the message is written in the queue (that is the queue is not full).

// Create or open an infinite user-defined write-only MessageQueue
WriteOnlyMessageQueue writeOnlyMessageQueue = MessageQueue.Create<WriteOnlyMessageQueue>(“MyQueueName”);

Message message = new Message(UTF8Encoding.UTF8.GetBytes(“Hello world!”));


// WRITE OPTIONS
// 1. block the current thread until a message can be written into the queue (that is the queue is not full).
writeOnlyMessageQueue.Write(message, true);


// 2. block the current thread for a max of 200 ms. If the message can’t be written during this interval, throw an exception.
try { writeOnlyMessageQueue.Write(message, 200); } catch (Exception ex) { }


// 3. don’t block the current thread. If a message can’t be written immediately, throw an exception.
try { writeOnlyMessageQueue.Write(message, false); } catch (Exception ex) { }

ReadOnlyMessageQueue

It’s a concrete class for reading messages from a queue. The class exposes some overloads of the Read() method in order read a message from a queue and choose whether to block the calling thread until a message can be read from the queue (that is the queue is not empty).

// Create or open an infinite user-defined read-only MessageQueue
ReadOnlyMessageQueue readOnlyMessageQueue = MessageQueue.Create<ReadOnlyMessageQueue>(“MyQueueName”);
Message message = null;

// READ OPTIONS
// 1. block the current thread until a message can be read from the queue.
message = readOnlyMessageQueue.Read(true);

// 2. block the current thread for a max of 200 ms. If no message has been read during this interval, throw an exception.
try { message = readOnlyMessageQueue.Read(200); } catch (Exception ex) { … }

// 3. don’t block the current thread. If a message can’t be read immediately, throw an exception.
try { message = readOnlyMessageQueue.Read(false); } catch (Exception ex) { … }

AutoReadOnlyMessageQueue

It’s a concrete class derived from ReadOnlyMessageQueue. It uses a monitoring thread useful to automatically read messages after they are written in the queue. So, the class exposes a MessageRead event which is fired for each message read from the queue.

// Create or open an infinite user-defined read-only MessageQueue
AutoReadOnlyMessageQueue autoReadOnlyMessageQueue = MessageQueue.Create<AutoReadOnlyMessageQueue>(“MyQueueName”);

// Starts monitoring the queue.
// New messages will be read automatically and notified through the MessageRead event.
autoReadOnlyMessageQueue.Start();
autoReadOnlyMessageQueue.MessageRead += (s, e) => { byte[] messageBytes = e.Message.Bytes; }; 

Another static method exposed by the MessageQueue class is OpenByHandle().  It allows you to open a  MessageQueue by using its handle. This method is suitable to open unnamed queues.

public static T OpenByHandle<T>(IntPtr queueHandle) where T : MessageQueue
public static T OpenByHandle<T>(IntPtr queueHandle, IntPtr processHandle) where T : MessageQueue

As you can see, in this case you need an handle to a source process that owns the message queue, while the queue handle is the same returned by the Create() method.
Finally I’ve created a simple smart device project for testing this class library (Visual Studio 2008 / Framework 2.0 or 3.5) just refactoring the example proposed by the author of the MSDN article mentioned above.

You can download source code here.

Here’s a screenshot:

HTH

Posted in .NET Framework, Compact Framework | 5 Comments »