「
GDD Blog: [.NET]MailSlot(その2)」で掲載しましたMailSlot操作クラスですが、ReadFileで受信待機をします。そのため、
- 何かしら情報を受信しないと終わらない 
- すべての受信が終わるまで、受信メッセージを取得する方法が無い 
という問題がありました。そこで
- 待機ループし、終了フラグを監視する 
- イベントを発行する機構を実装する 
- IDisposableをインプリメント
することにしました。 
以下、メールスロットを送受信するクラスです。
public class MailSlot : IDisposable
{
    #region Win32 API宣言
    [DllImport("kernel32.dll")]
    static extern SafeFileHandle CreateMailslot(
        string lpName,          
        uint nMaxMessageSize,   
        uint lReadTimeout,      
        IntPtr lpSecurityAttributes);   
    [DllImport("kernel32.dll")]
    static extern bool GetMailslotInfo(
        SafeFileHandle hMailslot,   
        ref uint lpMaxMessageSize,    
        ref uint lpNextSize,          
        ref uint lpMessageCount,      
        ref uint lpReadTimeout);      
    [DllImport("kernel32.dll")]
    static extern bool SetMailslotInfo(
        SafeFileHandle hMailslot,   
        uint lReadTimeout);         
    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(SafeFileHandle hMailslot);
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private static extern SafeFileHandle CreateFile(
        string lpFileName,              
        DesiredAccess dwDesiredAccess,  
        ShareMode dwShareMode,          
        int lpSecurityAttributes,       
        CreationDisposition dwCreationDisposition,  
        FlagsAndAttributes dwFlagsAndAttributes,    
        IntPtr hTemplateFile);          
    #endregion
    #region 列挙体
    private enum DesiredAccess : uint
    {
        GENERIC_READ = 0x80000000,
        GENERIC_WRITE = 0x40000000,
        GENERIC_EXECUTE = 0x20000000
    }
    private enum ShareMode : uint
    {
        FILE_SHARE_READ = 0x00000001,
        FILE_SHARE_WRITE = 0x00000002,
        FILE_SHARE_DELETE = 0x00000004
    }
    private enum CreationDisposition : uint
    {
        CREATE_NEW = 1,
        CREATE_ALWAYS = 2,
        OPEN_EXISTING = 3,
        OPEN_ALWAYS = 4,
        TRUNCATE_EXISTING = 5
    }
    private enum FlagsAndAttributes : uint
    {
        FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
        FILE_ATTRIBUTE_ENCRYPTED = 0x00004000,
        FILE_ATTRIBUTE_HIDDEN = 0x00000002,
        FILE_ATTRIBUTE_NORMAL = 0x00000080,
        FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
        FILE_ATTRIBUTE_OFFLINE = 0x00001000,
        FILE_ATTRIBUTE_READONLY = 0x00000001,
        FILE_ATTRIBUTE_SYSTEM = 0x00000004,
        FILE_ATTRIBUTE_TEMPORARY = 0x00000100
    }
    private enum MailSlotStatus : uint
    {
        MAILSLOT_NO_MESSAGE = 0xffffffff,
    }
    #endregion
    
    
    
    
    
    public delegate void ReceiveEventHandler(object sender, ReceiveEventArgs e);
    
    public event ReceiveEventHandler receive;
    private SafeFileHandle slotHandle = null;
    
    
    
    public SafeFileHandle SlotHandle
    {
        get { return slotHandle; }
        set { slotHandle = value; }
    }
    private bool receiveLoop = true;
    
    
    
    public bool ReceiveLoop
    {
        get { return receiveLoop; }
        set { receiveLoop = value; }
    }
    
    
    
    public MailSlot()
    {
    }
    
    
    
    
    
    
    public void Open(string slotName, uint maxMessageSize, uint readTimeout)
    {
        
        SlotHandle = CreateMailslot(slotName, maxMessageSize, readTimeout, (IntPtr)0);
    }
    
    
    
    public void Close()
    {
        
        lock (this)
        {
            if (SlotHandle != null)
            {
                
                CloseHandle(SlotHandle);
                SlotHandle = null;
            }
        }
    }
    
    
    
    public void ReadMailSlot()
    {
        try
        {
            
            while (ReceiveLoop)
            {
                
                uint msgMaxCnt = 1;
                uint nextSize = 0;
                uint msgCnt = 0;
                uint timeout = 0;
                
                if (!GetMailslotInfo(SlotHandle, ref msgMaxCnt, ref nextSize, ref msgCnt, ref timeout))
                {
                    System.Diagnostics.Debug.WriteLine("GetMailslotInfo失敗!!");
                    continue;
                }
                
                if (msgCnt > 0 && nextSize != (uint)MailSlotStatus.MAILSLOT_NO_MESSAGE)
                {
                    
                    FileStream fs = new FileStream(SlotHandle, FileAccess.Read);
                    byte[] buf = new byte[msgMaxCnt];
                    int len = fs.Read(buf, 0, buf.Length);
                    
                    ReceiveEventArgs e = new ReceiveEventArgs(Encoding.UTF8.GetString(buf, 0, len));
                    OnReceive(e);
                    
                    if (e.ReceiveEnd)
                    {
                        ReceiveLoop = false;
                    }
                    
                    
                }
                else
                {
                    
                    Thread.Sleep(500);
                }
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
            System.Diagnostics.Debug.WriteLine(ex.StackTrace);
            throw ex;
        }
    }
    
    
    
    
    protected virtual void OnReceive(ReceiveEventArgs e)
    {
        if (receive != null)
        {
            receive(this, e);
        }
    }
    #region IDisposable メンバ
    
    
    
    public void Dispose()
    {
        Close();
    }
    #endregion
    
    
    
    
    
    public static void WriteMailSlot(string slot, string message)
    {
        try
        {
            
            SafeFileHandle fileHandle = CreateFile(slot,
                    DesiredAccess.GENERIC_READ | DesiredAccess.GENERIC_WRITE,
                    ShareMode.FILE_SHARE_READ | ShareMode.FILE_SHARE_WRITE,
                    0,
                    CreationDisposition.OPEN_EXISTING,
                    FlagsAndAttributes.FILE_ATTRIBUTE_NORMAL,
                    (IntPtr)0);
            
            using (FileStream fs = new FileStream(fileHandle, FileAccess.Write))
            {
                byte[] msg = Encoding.UTF8.GetBytes(message);
                fs.Write(msg, 0, msg.Length);
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message);
            System.Diagnostics.Debug.WriteLine(ex.StackTrace);
            throw ex;
        }
    }
}
以下、受信イベントオブジェクトクラスです。
public class ReceiveEventArgs : EventArgs
{
    private string message;
    
    
    
    public string Message
    {
        get { return message; }
    }
    private bool receiveEnd = false;
    
    
    
    public bool ReceiveEnd
    {
        get { return receiveEnd; }
        set { receiveEnd = value; }
    }
    
    
    
    
    public ReceiveEventArgs(string msg)
    {
        message = msg;
    }
}
使うほうはこんな感じ。
private void btnMLReceive2_Click(object sender, EventArgs e)
{
    using (MailSlot slot = new MailSlot())
    {
        
        slot.receive += new MailSlot.ReceiveEventHandler(slot_receive2);
        slot.Open(txtMQPath.Text, 512, 0xffff);
        slot.ReadMailSlot();
        
        slot.Close();
    }
}
private void slot_receive2(object sender, ReceiveEventArgs e)
{
    
    txtMQRecieve.AppendText(e.Message);
    txtMQRecieve.AppendText(Environment.NewLine);
    
    if (e.Message == "TERMINATE")
    {
        
        e.ReceiveEnd = true;
    }
}