202 lines
6.1 KiB
C#
202 lines
6.1 KiB
C#
/******************************************************************************
|
||
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
|
||
* CopyRight (C) 2012-2021 ShenYongHua(沈永华).
|
||
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com
|
||
*
|
||
* Blog: https://www.cnblogs.com/yhuse
|
||
* Gitee: https://gitee.com/yhuse/SunnyUI
|
||
* GitHub: https://github.com/yhuse/SunnyUI
|
||
*
|
||
* SunnyUI.dll can be used for free under the GPL-3.0 license.
|
||
* If you use this code, please keep this note.
|
||
* 如果您使用此代码,请保留此说明。
|
||
******************************************************************************
|
||
* 文件名称: UMMFile.cs
|
||
* 文件说明: 多进程通信类
|
||
* 当前版本: V3.0
|
||
* 创建日期: 2021-09-05
|
||
*
|
||
* 2021-09-05: V3.0.6 增加文件说明
|
||
******************************************************************************
|
||
* 用法:
|
||
* 1、分别在不同的进程Demo1、Demo2中创建通信类
|
||
* 在Demo1里创建通信类mmfile1:
|
||
var mmfile1 = new MMFile("Demo1");
|
||
mmfile1.Start();
|
||
mmfile1.OnMessage += Mmfile1_OnMessage;
|
||
|
||
* 在Demo2里创建通信类mmfile2:
|
||
var mmfile2 = new MMFile("Demo2");
|
||
mmfile2.Start();
|
||
mmfile2.OnMessage += Mmfile2_OnMessage;
|
||
|
||
* 2、发送消息
|
||
* Demo1发送一条消息给Demo2:
|
||
mmfile1.Write("Demo2", "Hello world.");
|
||
|
||
* 3、接收消息
|
||
* Demo2的接收消息事件里处理消息,注意,该消息与界面交互需用Invoke
|
||
private void Mmfile2_OnMessage(object sender, MMFileEventArgs e)
|
||
{
|
||
AddMessage(e);
|
||
}
|
||
|
||
private void AddMessage(MMFileEventArgs e)
|
||
{
|
||
if (listBox1.InvokeRequired)
|
||
{
|
||
listBox1.Invoke(new Action<MMFileEventArgs>(AddMessage), e);
|
||
}
|
||
else
|
||
{
|
||
listBox1.Items.Add(e.Source + "," + e.Value);
|
||
}
|
||
}
|
||
|
||
* 4、关闭及销毁通信类
|
||
* mmfile1.Stop();
|
||
mmfile1.Dispose();
|
||
* mmfile2.Stop();
|
||
mmfile2.Dispose();
|
||
******************************************************************************/
|
||
|
||
using System;
|
||
using System.IO.MemoryMappedFiles;
|
||
using System.Text;
|
||
using System.Threading;
|
||
|
||
namespace Sunny.UI
|
||
{
|
||
public sealed class MMFile : BackgroundWorkerEx, IDisposable
|
||
{
|
||
public string MapName { get; }
|
||
public int Capacity { get; }
|
||
|
||
public MMFile(string mapName, int capacity = 4096)
|
||
{
|
||
if (!FileEx.IsValidFileName(mapName))
|
||
{
|
||
throw new Exception("MapName is not valid.");
|
||
}
|
||
|
||
MapName = mapName;
|
||
WorkerDelay = 10;
|
||
Capacity = Math.Max(4096, capacity);
|
||
|
||
var mmf = MemoryMappedFile.CreateOrOpen(MapName, Capacity, MemoryMappedFileAccess.ReadWrite);
|
||
using (var accessor = mmf.CreateViewAccessor(0, Capacity))
|
||
{
|
||
var value = accessor.ReadBoolean(0);
|
||
if (!value) accessor.Write(0, false);
|
||
}
|
||
}
|
||
|
||
public event MMFileEventHandler OnMessage;
|
||
|
||
protected override void DoWorker()
|
||
{
|
||
try
|
||
{
|
||
if (ExistsValue())
|
||
{
|
||
var message = Read();
|
||
OnMessage?.Invoke(this, new MMFileEventArgs(message.Source, message.Value));
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Console.WriteLine(e);
|
||
}
|
||
}
|
||
|
||
public void Write(string dest, string message)
|
||
{
|
||
var mmf = MemoryMappedFile.CreateOrOpen(dest, Capacity, MemoryMappedFileAccess.ReadWrite);
|
||
using (var accessor = mmf.CreateViewAccessor(0, Capacity))
|
||
{
|
||
if (accessor.ReadBoolean(0))
|
||
{
|
||
Thread.Sleep(10);
|
||
}
|
||
|
||
var data = Encoding.Unicode.GetBytes(MapName);
|
||
accessor.Write(128, data.Length);
|
||
accessor.WriteArray(128 + 4, data, 0, data.Length);
|
||
|
||
data = Encoding.Unicode.GetBytes(message);
|
||
accessor.Write(1024, data.Length);
|
||
accessor.WriteArray(1024 + 4, data, 0, data.Length);
|
||
|
||
accessor.Write(0, true);
|
||
}
|
||
}
|
||
|
||
private Message Read()
|
||
{
|
||
Message message = new Message();
|
||
var mmf = MemoryMappedFile.CreateOrOpen(MapName, Capacity, MemoryMappedFileAccess.ReadWrite);
|
||
using (var accessor = mmf.CreateViewAccessor(0, Capacity))
|
||
{
|
||
var len = accessor.ReadInt32(128);
|
||
var data = new byte[len];
|
||
accessor.ReadArray(128 + 4, data, 0, len);
|
||
message.Source = Encoding.Unicode.GetString(data);
|
||
|
||
len = accessor.ReadInt32(1024);
|
||
data = new byte[len];
|
||
accessor.ReadArray(1024 + 4, data, 0, len);
|
||
message.Value = Encoding.Unicode.GetString(data);
|
||
|
||
accessor.Write(0, false);
|
||
return message;
|
||
}
|
||
}
|
||
|
||
private bool ExistsValue()
|
||
{
|
||
var mmf = MemoryMappedFile.CreateOrOpen(MapName, Capacity, MemoryMappedFileAccess.ReadWrite);
|
||
using (var accessor = mmf.CreateViewAccessor(0, Capacity))
|
||
{
|
||
return accessor.ReadBoolean(0);
|
||
}
|
||
}
|
||
|
||
internal struct Message
|
||
{
|
||
public string Source { get; set; }
|
||
public string Value { get; set; }
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
Stop();
|
||
try
|
||
{
|
||
var mmf = MemoryMappedFile.OpenExisting(MapName);
|
||
mmf.Dispose();
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Console.WriteLine(e);
|
||
}
|
||
}
|
||
|
||
~MMFile()
|
||
{
|
||
Dispose();
|
||
}
|
||
}
|
||
|
||
public delegate void MMFileEventHandler(object sender, MMFileEventArgs e);
|
||
public class MMFileEventArgs : EventArgs
|
||
{
|
||
public string Source { get; set; }
|
||
public string Value { get; set; }
|
||
|
||
public MMFileEventArgs(string source, string value)
|
||
{
|
||
Source = source;
|
||
Value = value;
|
||
}
|
||
}
|
||
} |