initial commit
This commit is contained in:
574
Handler/Sub/MemoryMapCore/Core.cs
Normal file
574
Handler/Sub/MemoryMapCore/Core.cs
Normal file
@@ -0,0 +1,574 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AR.MemoryMap
|
||||
{
|
||||
public abstract class Core
|
||||
{
|
||||
protected ManualResetEvent mre;
|
||||
protected MemoryMappedFile mmf;
|
||||
protected Mutex mutex;
|
||||
protected bool mutexCreated;
|
||||
protected Func<bool> StartAction;
|
||||
protected Func<bool> StopAction;
|
||||
string MapFileName = string.Empty;
|
||||
public int WriteTime = 100;
|
||||
public int ReadTime = 100;
|
||||
int MapSize = 100;
|
||||
public bool Init { get; set; } = false;
|
||||
Task loop;
|
||||
protected bool brun = false;
|
||||
public int LoopDelay { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
public Core(string mapFileName, int mapSize, int loopDelay = 50)
|
||||
{
|
||||
LoopDelay = loopDelay;
|
||||
this.MapFileName = mapFileName;
|
||||
this.MapSize = mapSize;
|
||||
this.monitorvalue = new byte[mapSize];
|
||||
mre = new ManualResetEvent(false);
|
||||
}
|
||||
~Core()
|
||||
{
|
||||
brun = false;
|
||||
}
|
||||
|
||||
public bool Start()
|
||||
{
|
||||
Init = StartAction.Invoke();
|
||||
return Init;
|
||||
}
|
||||
public void StartMonitor()
|
||||
{
|
||||
if (Init == false) return;
|
||||
if (IsMonitorRun) return;
|
||||
|
||||
|
||||
brun = true;
|
||||
loop = Task.Factory.StartNew(() =>
|
||||
{
|
||||
Monitor_Loop();
|
||||
});
|
||||
}
|
||||
public void StopMonitor()
|
||||
{
|
||||
brun = false;
|
||||
}
|
||||
public bool IsMonitorRun
|
||||
{
|
||||
get
|
||||
{
|
||||
if (loop == null) return false;
|
||||
if (loop.IsCompleted) return false;
|
||||
if (loop.IsCanceled) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SetMonitorTarget(bool All)
|
||||
{
|
||||
if (mre.WaitOne(100) == false) return false;
|
||||
|
||||
|
||||
mre.Set();
|
||||
return true;
|
||||
}
|
||||
|
||||
byte[] monitorvalue;
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
StopAction.Invoke();
|
||||
}
|
||||
private void Monitor_Loop()
|
||||
{
|
||||
while (brun)
|
||||
{
|
||||
//작업가능확인
|
||||
bool readok = false;
|
||||
byte[] value = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (mre.WaitOne(100))
|
||||
{
|
||||
try
|
||||
{
|
||||
//메모리접근 권한 확인
|
||||
if (MutexWaitOne(100))
|
||||
{
|
||||
//값을 읽은 경우
|
||||
if (ReadBytes(0, this.MapSize, out value))
|
||||
{
|
||||
readok = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
finally { mutex.ReleaseMutex(); }
|
||||
}
|
||||
}
|
||||
finally { mre.Set(); }
|
||||
|
||||
|
||||
if (readok)
|
||||
{
|
||||
//값의 변화가 있다면 이벤트 발생
|
||||
List<int> changeindex = new List<int>();
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
if (value[i] != monitorvalue[i]) changeindex.Add(i);
|
||||
}
|
||||
if (changeindex.Any())
|
||||
{
|
||||
ValueChanged.Invoke(this, new monitorvalueargs(changeindex.ToArray(), monitorvalue, value));
|
||||
}
|
||||
//신규값을 업데이트
|
||||
Array.Copy(value, monitorvalue, value.Length);
|
||||
}
|
||||
|
||||
//write
|
||||
System.Threading.Thread.Sleep(LoopDelay);
|
||||
}
|
||||
}
|
||||
public bool MutexWaitOne(int milli)
|
||||
{
|
||||
var MapFileSync = $"{MapFileName}{MapSize}";
|
||||
if (mutexCreated == false)
|
||||
{
|
||||
mutex = new Mutex(false, MapFileSync, out mutexCreated);
|
||||
return mutex.WaitOne(milli);
|
||||
}
|
||||
else
|
||||
{
|
||||
//이미생성된 경우에는 에러처리를 해야한다
|
||||
try
|
||||
{
|
||||
return mutex.WaitOne(milli);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//오류가있으니 다시 작성한다
|
||||
mutex = new Mutex(false, MapFileSync, out mutexCreated);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<monitorvalueargs> ValueChanged;
|
||||
public class monitorvalueargs : EventArgs
|
||||
{
|
||||
public byte[] newdata;
|
||||
public byte[] olddata;
|
||||
public int[] idxlist;
|
||||
public monitorvalueargs(int[] idxs, byte[] beforedata, byte[] afterdata)
|
||||
{
|
||||
idxlist = new int[idxs.Length];
|
||||
Array.Copy(idxs, this.idxlist, idxs.Length);
|
||||
newdata = new byte[afterdata.Length];
|
||||
Array.Copy(afterdata, newdata, afterdata.Length);
|
||||
olddata = new byte[beforedata.Length];
|
||||
Array.Copy(beforedata, olddata, beforedata.Length);
|
||||
}
|
||||
}
|
||||
|
||||
#region "WRITE"
|
||||
public bool Write(int address, Boolean value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(value.GetType());
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Write(int address, byte[] value, int startIndex = 0, int size = 0)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
if (size == 0) size = Marshal.SizeOf(value.GetType());
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value,startIndex,size);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
public bool Write(int address, byte value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(value.GetType());
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
public bool Write(int address, string value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(type);
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
public bool Write(int address, Int32 value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(type);
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
public bool Write(int address, Int16 value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(type);
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
public bool Write(int address, UInt32 value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(type);
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
public bool Write(int address, UInt16 value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(type);
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
public bool Write(int address, Single value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(type);
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
public bool Write(int address, Double value)
|
||||
{
|
||||
if (Init == false) return false;
|
||||
if (MutexWaitOne(WriteTime) == false) return false;
|
||||
Type type = value.GetType();
|
||||
var size = Marshal.SizeOf(type);
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
writer.Write(value);
|
||||
mutex.ReleaseMutex();
|
||||
return true;
|
||||
}
|
||||
|
||||
//public bool Write<T>(int address, T value)
|
||||
//{
|
||||
// if (checktype(value.GetType()) == false) return false;
|
||||
// if (MutexWaitOne(3000) == false) return false;
|
||||
// var size = Marshal.SizeOf(typeof(T));
|
||||
// using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
// {
|
||||
// using (var reader = new BinaryWriter(stream))
|
||||
// {
|
||||
// var a = (byte[])Convert.ChangeType(value, typeof(byte[]));
|
||||
// reader.Write(a, 0, a.Length);
|
||||
// }
|
||||
// }
|
||||
// mutex.ReleaseMutex();
|
||||
// return true;
|
||||
//}
|
||||
#endregion
|
||||
#region "READ"
|
||||
public bool ReadSingle(int address, out Single value)
|
||||
{
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var retval = true;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 1;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = BitConverter.ToSingle(buffer, 0);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadDouble(int address, out double value)
|
||||
{
|
||||
var retval = true;
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 1;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = BitConverter.ToDouble(buffer, 0);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadBytes(int address, int size, out byte[] value)
|
||||
{
|
||||
var retval = true;
|
||||
value = new byte[size];
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
reader.Read(value, 0, size);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadByte(int address, out byte value)
|
||||
{
|
||||
var retval = true;
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 1;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = buffer.First();
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadInt16(int address, out Int16 value)
|
||||
{
|
||||
var retval = true;
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 4;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = BitConverter.ToInt16(buffer, 0);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadInt32(int address, out Int32 value)
|
||||
{
|
||||
var retval = true;
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 4;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = BitConverter.ToInt32(buffer, 0);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadInt64(int address, out Int64 value)
|
||||
{
|
||||
var retval = true;
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 4;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = BitConverter.ToInt64(buffer, 0);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadUInt16(int address, out UInt16 value)
|
||||
{
|
||||
var retval = true;
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 4;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = BitConverter.ToUInt16(buffer, 0);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadUInt32(int address, out UInt32 value)
|
||||
{
|
||||
var retval = true;
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 4;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = BitConverter.ToUInt32(buffer, 0);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
public bool ReadUInt64(int address, out UInt64 value)
|
||||
{
|
||||
var retval = true;
|
||||
value = 0;
|
||||
if (Init == false) return false;
|
||||
var type = value.GetType();
|
||||
if (MutexWaitOne(ReadTime) == false) return false;
|
||||
var size = 4;
|
||||
using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
byte[] buffer = new byte[size];
|
||||
reader.Read(buffer, 0, size);
|
||||
value = BitConverter.ToUInt64(buffer, 0);
|
||||
}
|
||||
}
|
||||
mutex.ReleaseMutex();
|
||||
return retval;
|
||||
}
|
||||
|
||||
//public bool Read<T>(int address, out T value) where T : IConvertible
|
||||
//{
|
||||
// var retval = true;
|
||||
// value = default(T);
|
||||
// var type = value.GetType();
|
||||
// if (checktype(type) == false) return false;
|
||||
|
||||
// if (MutexWaitOne(3000) == false) return false;
|
||||
// var size = Marshal.SizeOf(typeof(T));
|
||||
// using (MemoryMappedViewStream stream = mmf.CreateViewStream(address, size))
|
||||
// {
|
||||
// using (var reader = new BinaryReader(stream))
|
||||
// {
|
||||
// byte[] buffer = new byte[size];
|
||||
// reader.Read(buffer, 0, size);
|
||||
// if (type == typeof(Int32))
|
||||
// value = (T)Convert.ChangeType(BitConverter.ToInt32(buffer, 0), typeof(T));
|
||||
// else if (type == typeof(UInt32))
|
||||
// value = (T)Convert.ChangeType(BitConverter.ToUInt32(buffer, 0), typeof(T));
|
||||
// else if (type == typeof(Int16))
|
||||
// value = (T)Convert.ChangeType(BitConverter.ToInt16(buffer, 0), typeof(T));
|
||||
// else if (type == typeof(UInt16))
|
||||
// value = (T)Convert.ChangeType(BitConverter.ToUInt16(buffer, 0), typeof(T));
|
||||
// else if (type == typeof(byte))
|
||||
// value = (T)Convert.ChangeType(buffer[0], typeof(T));
|
||||
// else if (type == typeof(string))
|
||||
// value = (T)Convert.ChangeType(System.Text.Encoding.Default.GetString(buffer), typeof(T));
|
||||
// else retval = false;
|
||||
// }
|
||||
// }
|
||||
// mutex.ReleaseMutex();
|
||||
// return retval;
|
||||
//}
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 지정한 타입이 호환되는 타입인가?
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
//bool checktype(Type value)
|
||||
//{
|
||||
// if (value == typeof(Int32)) return true;
|
||||
// else if (value == typeof(UInt32)) return true;
|
||||
// else if (value == typeof(Int16)) return true;
|
||||
// else if (value == typeof(UInt16)) return true;
|
||||
// else if (value == typeof(byte)) return true;
|
||||
// else if (value == typeof(string)) return true;
|
||||
// else return false;
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user