数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

使用共享内存在进程之间传送数据


发布日期:2020年04月16日
 
使用共享内存在进程之间传送数据

今日在项目中碰到一个问题就是一个程序的两个进程之间需要频繁的传送数据具体的来说是一个需要频繁的发送数据而另一个实例需要频繁的访问获得这些数据当然这个问题是有很多解的例如数据库再例如文件可是因为这个频繁程度太高了例如一秒钟十次在这种情况下使用数据库或者是文件可能都不是一个Good Idea

Update: 其实开始想到的方案还包括Remoting Socket之类的不过明显的是小题大做杀鸡用牛刀了呵呵所以最后也就放弃了

那么什么解决方案好呢?众所周知内存的速度是除了CPU缓存外最快的当然是我们的首选了可是看遍了Net的类库也没有找到可以用来实现这个方案的办法看来只能依靠Win API了在网上得到资料可以使用API开辟共享内存从而达到在不同的进程之间共享数据的可能

关键API类

view sourceprint?public static class API

{

[DllImport(userdll CharSet = CharSetAuto)]

public static extern IntPtr SendMessage(IntPtr hWnd int Msg int wParam IntPtr lParam);

[DllImport(Kerneldll CharSet = CharSetAuto)]

public static extern IntPtr CreateFileMapping(int hFile IntPtr lpAttributes uint flProtect uint dwMaxSizeHi uint dwMaxSizeLow string lpName);

[DllImport(Kerneldll CharSet = CharSetAuto)]

public static extern IntPtr OpenFileMapping(int dwDesiredAccess [MarshalAs(UnmanagedTypeBool)] bool bInheritHandle string lpName);

[DllImport(Kerneldll CharSet = CharSetAuto)]

public static extern IntPtr MapViewOfFile(IntPtr hFileMapping uint dwDesiredAccess uint dwFileOffsetHigh uint dwFileOffsetLow uint dwNumberOfBytesToMap);

[DllImport(Kerneldll CharSet = CharSetAuto)]

public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);

[DllImport(Kerneldll CharSet = CharSetAuto)]

public static extern bool CloseHandle(IntPtr handle);

[DllImport(kernel EntryPoint = GetLastError)]

public static extern int GetLastError();

[DllImport(msvcrtdll SetLastError = true)]

public static extern int memcmp(IntPtr ptr IntPtr ptr int count);

[DllImport(msvcrtdll SetLastError = true)]

public static extern unsafe int memcmp(void* ptr void* ptr int count);

[DllImport(ntdlldll)]

public static extern int RtlCompareMemory(IntPtr Destination IntPtr Source int Length);

public const int ERROR_ALREADY_EXISTS = ;

public const int FILE_MAP_COPY = x;

public const int FILE_MAP_WRITE = x;

public const int FILE_MAP_READ = x;

public const int FILE_MAP_ALL_ACCESS = x | x;

public const int PAGE_READONLY = x;

public const int PAGE_READWRITE = x;

public const int PAGE_WRITECOPY = x;

public const int PAGE_EXECUTE = x;

public const int PAGE_EXECUTE_READ = x;

public const int PAGE_EXECUTE_READWRITE = x;

public const int SEC_COMMIT = x;

public const int SEC_IMAGE = x;

public const int SEC_NOCACHE = x;

public const int SEC_RESERVE = x;

public const int INVALID_HANDLE_VALUE = ;

}

代码实现

view sourceprint?public enum MemoryResult

{

Success

NotInitialized

NoChange

Failed

}

public class ShareMemory<T> : IDisposable

where T : class

{

IntPtr m_hSharedMemoryFile = IntPtrZero;

IntPtr m_pwData = IntPtrZero;

bool m_bAlreadyExist = false;

bool m_bInit = false;

long m_MemSize = ;

int m_size;

byte[] m_lastData;

public ShareMemory()

{

}

~ShareMemory()

{

Close();

}

/// <summary>

/// 初始化共享内存

/// </summary>

public MemoryResult Init(string strName)

{

m_size = ; //固定K

var lngSize = m_size;

if (lngSize <= || lngSize > x) lngSize = x;

m_MemSize = lngSize;

if (strNameLength > )

{

//创建内存共享体 (INVALID_HANDLE_VALUE)

m_hSharedMemoryFile = APICreateFileMapping(APIINVALID_HANDLE_VALUE IntPtrZero (uint)APIPAGE_READWRITE (uint)lngSize strName);

if (m_hSharedMemoryFile == IntPtrZero)

{

m_bAlreadyExist = false;

m_bInit = false;

return MemoryResultFailed; //创建共享体失败

}

else

{

if (APIGetLastError() == APIERROR_ALREADY_EXISTS) //已经创建

{

m_bAlreadyExist = true;

}

else //新创建

{

m_bAlreadyExist = false;

}

}

//

//创建内存映射

m_pwData = APIMapViewOfFile(m_hSharedMemoryFile APIFILE_MAP_WRITE (uint)lngSize);

if (m_pwData == IntPtrZero)

{

m_bInit = false;

APICloseHandle(m_hSharedMemoryFile);

return MemoryResultFailed; //创建内存映射失败

}

else

{

m_bInit = true;

if (m_bAlreadyExist == false)

{

//初始化

}

}

//

}

else

{

return MemoryResultFailed; //参数错误

}

return MemoryResultSuccess; //创建成功

}

/// <summary>

/// 关闭共享内存

/// </summary>

public void Close()

{

if (m_bInit)

{

APIUnmapViewOfFile(m_pwData);

APICloseHandle(m_hSharedMemoryFile);

}

}

/// <summary>

/// 读数据

/// </summary>

public unsafe MemoryResult Read(out T obj)

{

obj = default(T);

byte[] bytData = new byte[m_size];

if (m_bInit)

{

MarshalCopy(m_pwData bytData m_size);

if (m_lastData != null)

{

fixed (byte* p = m_lastData)

{

fixed (byte* p = bytData)

{

if (mcmp(p p m_size) == )

return MemoryResultNoChange;

}

}

}

m_lastData = bytData;

var fmt = new BinaryFormatter();

using (var ms = new MemoryStream(bytData))

{

try

{

obj = (T)fmtDeserialize(ms);

}

catch (SerializationException)

{

return MemoryResultFailed;

}

}

}

else

{

return MemoryResultNotInitialized; //共享内存未初始化

}

return MemoryResultSuccess; //读成功

}

/// <summary>

/// 写数据

/// </summary>

public MemoryResult Write(T obj)

{

var fmt = new BinaryFormatter();

byte[] bytData;

if (obj is byte[])

bytData = obj as byte[];

else

{

using (var ms = new MemoryStream())

{

fmtSerialize(ms obj);

bytData = msToArray();

}

}

if (m_bInit)

MarshalCopy(bytData m_pwData bytDataLength);

else

return MemoryResultNotInitialized; //共享内存未初始化

return MemoryResultSuccess; //写成功

}

#region IDisposable Members

public void Dispose()

{

Close();

}

#endregion

}

使用也很简单

view sourceprint?写数据

if (mem == null)

{

mem = new ShareMemory<ChannelStatus[]>();

memInit(ChannelStatus);

}

var xml = PhoneCallHelperSendRequest(PhoneCallActiongetChStatus);

foreach (XmlElement ele in xmlDocumentElementSelectNodes(chStatus))

{

var status = GetChannelStatusFromXElement(ele);

_status[statusChannel] = status;

}

memWrite(_statusValuesToArray());

读数据

using (var mem = new ShareMemory<ChannelStatus[]>())

{

if (memInit(ChannelStatus) != MemoryResultSuccess)

throw new Exception(内存初始化失败);

ChannelStatus[] status;

if (memRead(out status) == MemoryResultSuccess)

return status;

return null;

}

               

上一篇:数据层组件设计与数据传递一

下一篇:上传文件到数据库并从数据库读出