SunnyUI/SunnyUI/Units/UMMFile.cs
2021-09-05 17:27:19 +08:00

202 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
* CopyRight (C) 2012-2021 ShenYongHua(沈永华).
* QQ群56829229 QQ17612584 EMailSunnyUI@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;
}
}
}