示例#1
0
        /// <summary>
        /// This method initializes a shared memory inbox by creating one if
        /// it doesn't already exist or opening it if it does exist.  Note that
        /// all successful calls to Open() must be matched with a call to
        /// <see cref="Close" />. Note that to avoid problems, only one process
        /// may open an inbox using the SharedMemInbox class.  This method is threadsafe.
        /// </summary>
        /// <param name="name">
        /// Name of the inbox.  This can be a maximum of 128 characters and may
        /// not include the backslash (\) character.  The name is case sensitive.
        /// </param>
        /// <param name="maxMsgSize">
        /// Maximum message size allowed in bytes.  Note that this parameter must be
        /// the same across all instances of SharedMemInbox and SharedMemOutBox
        /// classes accessing this inbox.
        /// </param>
        /// <param name="onReceive">
        /// Delegate to be called when a message is placed in the inbox.  Note that
        /// this method will be called on a pool thread.
        /// </param>
        public unsafe void Open(string name, int maxMsgSize, SharedMemInboxReceiveDelegate onReceive)
        {
            if (name.Length > 128)
            {
                throw new ArgumentException("Name exceeds 128 characters.", "name");
            }

            if (name.IndexOfAny(new char[] { '/', '\\' }) != -1)
            {
                throw new ArgumentException("Name may not include forward or backslashes.");
            }

            if (maxMsgSize <= 0)
            {
                throw new ArgumentException("Invalid maximum message size.", "maxMsgSize");
            }

            lock (syncLock)
            {
                if (this.sharedMem != null)
                {
                    return;     // Already open
                }
                this.maxMsgSize = maxMsgSize;
                this.onReceive  = onReceive;
                this.onDispatch = new WaitCallback(OnDispatch);
                this.sharedMem  = new SharedMem();
                this.sharedMem.Open(name, maxMsgSize + MemHeaderSize, SharedMem.OpenMode.CREATE_OPEN);

                // Here's what the abbreviations mean:
                //
                //      LT  = LillTek
                //      SMI = SharedMemInBox
                //      NME = NewMessageEvent
                //      EBE = EmptyBoxEvent

                this.newMsgEvent   = new GlobalAutoResetEvent("LT:SMI:NME:" + name);
                this.emptyBoxEvent = new GlobalAutoResetEvent("LT:SMI:EBE:" + name);
                this.killThread    = false;
#if WINFULL
                this.recvThread = new Thread(new ThreadStart(ReceiveThreadProc));
#else
                this.recvThread = new CEThread(new ThreadStart(ReceiveThreadProc));
#endif
                this.recvThread.Start();

                byte *p;

                p = sharedMem.Lock();
                *(int *)&p[MaxMsgSizeOffset] = maxMsgSize;
                *(int *)&p[CurMsgSizeOffset] = 0;
                p[InboxListeningOffset]      = 1;
                sharedMem.Unlock();

                emptyBoxEvent.Set();
            }
        }
示例#2
0
        /// <summary>
        /// This method closes the inbox.  All successful calls to <see cref="Open" /> must
        /// be matched with a call to Close() to ensure that system resources
        /// are released in a timely manner.  Note that it is OK to call Close()
        /// even if the shared memory block is not open.  This method is threadsafe.
        /// </summary>
        public unsafe void Close()
        {
            lock (syncLock)
            {
                if (sharedMem == null)
                {
                    return;
                }

                byte *p;

                p = sharedMem.Lock();       // Indicate that we're not listening any more
                if (p != null)
                {
                    p[InboxListeningOffset] = 0;
                    sharedMem.Unlock();
                }
#if WINFULL
                // Wait up to 5 seconds for the receive thread to stop normally before
                // forcing the issue.

                int cWaits = 0;

                do
                {
                    killThread = true;      // Kill the receive thread
                    newMsgEvent.Set();
                    cWaits++;

                    if (cWaits == 5)
                    {
                        recvThread.Abort();
                    }
                } while (!recvThread.Join(1000));
#else
                newMsgEvent.Set();
                killThread = true;
                Thread.Sleep(5000);
                recvThread.Abort();
                recvThread.Join();
#endif
                sharedMem.Close();          // Release unmanaged resources
                newMsgEvent.Close();
                emptyBoxEvent.Close();

                sharedMem  = null;
                onReceive  = null;
                onDispatch = null;
            }
        }