在前面的SharedMemory中,我们通过P/Invoke完成了Win32中的Mapping File的使用..
通过这个,我们可以很方便的完成.NET应用程序的进程间通讯:)
但是,由于SharedMemory的映射空间的大小是在创建对象的时候固定了的,不能很方便的进行动态修改.
在某些场合就不方便使用..
有一个方法:
1,建立两个内存映射文件.
2,一个用于数据交换,另一个用于消息传送(比如当数据交换的那个内存映射文件的大小发生改变,用于通过另一方).
在这个基础上,我写了一个SharedMemoryEx..
大家可以看看,用用,看看有没有什么问题:)
注: 在CopyTo和CopyFrom前,都加入了一个检测函数.
CopyFrom前: 如果发现新的数据比申请的要大,就直接将原来的内存映射文件关掉,重新申请一个大的空间,同时修改MsgMem中的数据.
CopyTo前: 如果发现MsgMem中的消息为ChangeSize,而且新的Size大于当前的Size,就把当前的内存映射文件Release,再重新Open.
对于内存映射文件的创建者(用bool creator来标识),才可以重新Create,对于非创建者,才可以重新Open :)
希望大家喜欢:)
ps,代码就不用提供下载了吧??
...还是提供一个吧,最新的:)
SharedMemoryEx.zip
通过这个,我们可以很方便的完成.NET应用程序的进程间通讯:)
但是,由于SharedMemory的映射空间的大小是在创建对象的时候固定了的,不能很方便的进行动态修改.
在某些场合就不方便使用..
有一个方法:
1,建立两个内存映射文件.
2,一个用于数据交换,另一个用于消息传送(比如当数据交换的那个内存映射文件的大小发生改变,用于通过另一方).
在这个基础上,我写了一个SharedMemoryEx..
大家可以看看,用用,看看有没有什么问题:)
SharedMemoryEx#region SharedMemoryEx
class SharedMemoryEx : SharedMemory
{
Private Variable & Property#region Private Variable & Property
private bool creator;
private SharedMemory msgmem;
private string msgmemname;
private const int msgmemsize = 512;
private const string CHANGESIZE = "ChangeSize";
private const char SpliteChar = ':';
private int curlpSecuAttrs;
private ProtectionTypes curProtection;
private SectionTypes curSection;
private AccessTypes curAccess;
private int curOffset;
public override int Size
{
get
{
CheckTo();
return base.Size;
}
}
#endregion
Constructor & Dispose#region Constructor & Dispose
public SharedMemoryEx() : base(){}
public SharedMemoryEx(string MsgMemName):base()
{
msgmemname = MsgMemName;
}
public SharedMemoryEx(int Size,string Name,string MsgMemName):this(Size,Name,ProtectionTypes.PageReadWrite,SectionTypes.SecCommit,AccessTypes.Full,MsgMemName){}
public SharedMemoryEx(int Size, string Name, ProtectionTypes Protection, SectionTypes Section, AccessTypes Access,string MsgMemName)
{
Create(Size,Name,0,Protection,Section,Access,MsgMemName);
}
public override void Dispose()
{
msgmem.Dispose();
base.Dispose ();
}
#endregion
Common Functions#region Common Functions
Open#region Open
public override void Open(int Size, string Name, int Offset, AccessTypes Access)
{
creator = false;
if( msgmem == null)
{
msgmem = new SharedMemory();
msgmem.Open(msgmemsize,msgmemname,0,AccessTypes.Full);
}
curOffset = Offset;
curAccess = Access;
base.Open(Size,Name,Offset,Access);
}
public virtual void Open(string Name)
{
Open( Name, 0, AccessTypes.Read);
}
public virtual void Open(string Name, AccessTypes Access)
{
Open( Name, 0, Access);
}
public virtual void Open(string Name, int Offset)
{
Open(Name, Offset, AccessTypes.Read);
}
public virtual void Open(string Name,int Offset,AccessTypes Access)
{
Open(Name,Offset,Access,msgmemname);
}
public virtual void Open(string Name,string MsgMemName)
{
Open( Name, 0, AccessTypes.Read,MsgMemName);
}
public virtual void Open(string Name, AccessTypes Access,string MsgMemName)
{
Open( Name, 0, Access,MsgMemName);
}
public virtual void Open(string Name, int Offset,string MsgMemName)
{
Open(Name, Offset, AccessTypes.Read,MsgMemName);
}
public virtual void Open( string Name, int Offset, AccessTypes Access,string MsgMemName)
{
Open(0,Name,Offset,Access,MsgMemName);
}
public virtual void Open(int Size, string Name, int Offset, AccessTypes Access,string MsgMemName)
{
msgmemname = MsgMemName;
Open(Size,Name,Offset,Access);
}
#endregion
Create#region Create
public override void Create(int Size, string Name, int lpSecurityAttributes, ProtectionTypes Protection, SectionTypes Section, AccessTypes Access)
{
creator = true;
if( msgmem == null)
{
msgmem = new SharedMemory();
msgmem.Create(msgmemsize,msgmemname,ProtectionTypes.PageReadWrite,SectionTypes.SecCommit,AccessTypes.Full);
SendChangeMsg(Size);
}
curlpSecuAttrs = lpSecurityAttributes;
curProtection = Protection;
curSection = Section;
curAccess = Access;
base.Create (Size, Name, lpSecurityAttributes, Protection, Section, Access);
}
public void Create(int Size, string Name, int lpSecurityAttributes, ProtectionTypes Protection, SectionTypes Section, AccessTypes Access,string MsgMemName)
{
msgmemname = MsgMemName;
Create(Size,Name,lpSecurityAttributes,Protection,Section,Access);
}
#endregion
CopyXXX#region CopyXXX
public override void CopyFrom(byte[] source, int startIndex, int length)
{
CheckFrom(length);
base.CopyFrom (source, startIndex, length);
}
private void CheckFrom(int length)
{
if( length > Size)
{
if( !creator)
{
throw new ApplicationException("Can't Write so many bytes. Writalbe size " + Size + " .Want write size " + length);
}
// byte[] msg = Encoding.Unicode.GetBytes( CHANGESIZE + SpliteChar);
// byte[] bysizes = BitConverter.GetBytes(length);
// byte[] temp = new byte[msg.Length + bysizes.Length];
// Array.Copy(msg,0,temp,0,msg.Length);
// Array.Copy(bysizes,0,temp,msg.Length,bysizes.Length);
SendChangeMsg(length);
Create(length,Name,curlpSecuAttrs,curProtection,curSection,curAccess);
}
}
private void SendChangeMsg(int length)
{
msgmem.CopyFrom( CHANGESIZE + SpliteChar + length);
}
public override void CopyTo( byte[] destination, int startIndex, int length)
{
CheckTo();
base.CopyTo (destination, startIndex, length);
}
private void CheckTo()
{
if( creator )
{
return;
}
int realsize = ReceiveChangeMsg();
if( size < realsize)
{
Open( realsize,Name,curOffset,curAccess);
}
}
private void ReceiveChangeMsg(out int length)
{
length = ReceiveChangeMsg();
}
private int ReceiveChangeMsg()
{
string[] msgs = msgmem.CopyToString().Split( SpliteChar);
if( msgs.Length != 2 || msgs[0] != CHANGESIZE)
{
return 0;
}
return int.Parse( msgs[1]);
}
#endregion
#endregion
}
#endregion
class SharedMemoryEx : SharedMemory
{
Private Variable & Property#region Private Variable & Property
private bool creator;
private SharedMemory msgmem;
private string msgmemname;
private const int msgmemsize = 512;
private const string CHANGESIZE = "ChangeSize";
private const char SpliteChar = ':';
private int curlpSecuAttrs;
private ProtectionTypes curProtection;
private SectionTypes curSection;
private AccessTypes curAccess;
private int curOffset;
public override int Size
{
get
{
CheckTo();
return base.Size;
}
}
#endregion
Constructor & Dispose#region Constructor & Dispose
public SharedMemoryEx() : base(){}
public SharedMemoryEx(string MsgMemName):base()
{
msgmemname = MsgMemName;
}
public SharedMemoryEx(int Size,string Name,string MsgMemName):this(Size,Name,ProtectionTypes.PageReadWrite,SectionTypes.SecCommit,AccessTypes.Full,MsgMemName){}
public SharedMemoryEx(int Size, string Name, ProtectionTypes Protection, SectionTypes Section, AccessTypes Access,string MsgMemName)
{
Create(Size,Name,0,Protection,Section,Access,MsgMemName);
}
public override void Dispose()
{
msgmem.Dispose();
base.Dispose ();
}
#endregion
Common Functions#region Common Functions
Open#region Open
public override void Open(int Size, string Name, int Offset, AccessTypes Access)
{
creator = false;
if( msgmem == null)
{
msgmem = new SharedMemory();
msgmem.Open(msgmemsize,msgmemname,0,AccessTypes.Full);
}
curOffset = Offset;
curAccess = Access;
base.Open(Size,Name,Offset,Access);
}
public virtual void Open(string Name)
{
Open( Name, 0, AccessTypes.Read);
}
public virtual void Open(string Name, AccessTypes Access)
{
Open( Name, 0, Access);
}
public virtual void Open(string Name, int Offset)
{
Open(Name, Offset, AccessTypes.Read);
}
public virtual void Open(string Name,int Offset,AccessTypes Access)
{
Open(Name,Offset,Access,msgmemname);
}
public virtual void Open(string Name,string MsgMemName)
{
Open( Name, 0, AccessTypes.Read,MsgMemName);
}
public virtual void Open(string Name, AccessTypes Access,string MsgMemName)
{
Open( Name, 0, Access,MsgMemName);
}
public virtual void Open(string Name, int Offset,string MsgMemName)
{
Open(Name, Offset, AccessTypes.Read,MsgMemName);
}
public virtual void Open( string Name, int Offset, AccessTypes Access,string MsgMemName)
{
Open(0,Name,Offset,Access,MsgMemName);
}
public virtual void Open(int Size, string Name, int Offset, AccessTypes Access,string MsgMemName)
{
msgmemname = MsgMemName;
Open(Size,Name,Offset,Access);
}
#endregion
Create#region Create
public override void Create(int Size, string Name, int lpSecurityAttributes, ProtectionTypes Protection, SectionTypes Section, AccessTypes Access)
{
creator = true;
if( msgmem == null)
{
msgmem = new SharedMemory();
msgmem.Create(msgmemsize,msgmemname,ProtectionTypes.PageReadWrite,SectionTypes.SecCommit,AccessTypes.Full);
SendChangeMsg(Size);
}
curlpSecuAttrs = lpSecurityAttributes;
curProtection = Protection;
curSection = Section;
curAccess = Access;
base.Create (Size, Name, lpSecurityAttributes, Protection, Section, Access);
}
public void Create(int Size, string Name, int lpSecurityAttributes, ProtectionTypes Protection, SectionTypes Section, AccessTypes Access,string MsgMemName)
{
msgmemname = MsgMemName;
Create(Size,Name,lpSecurityAttributes,Protection,Section,Access);
}
#endregion
CopyXXX#region CopyXXX
public override void CopyFrom(byte[] source, int startIndex, int length)
{
CheckFrom(length);
base.CopyFrom (source, startIndex, length);
}
private void CheckFrom(int length)
{
if( length > Size)
{
if( !creator)
{
throw new ApplicationException("Can't Write so many bytes. Writalbe size " + Size + " .Want write size " + length);
}
// byte[] msg = Encoding.Unicode.GetBytes( CHANGESIZE + SpliteChar);
// byte[] bysizes = BitConverter.GetBytes(length);
// byte[] temp = new byte[msg.Length + bysizes.Length];
// Array.Copy(msg,0,temp,0,msg.Length);
// Array.Copy(bysizes,0,temp,msg.Length,bysizes.Length);
SendChangeMsg(length);
Create(length,Name,curlpSecuAttrs,curProtection,curSection,curAccess);
}
}
private void SendChangeMsg(int length)
{
msgmem.CopyFrom( CHANGESIZE + SpliteChar + length);
}
public override void CopyTo( byte[] destination, int startIndex, int length)
{
CheckTo();
base.CopyTo (destination, startIndex, length);
}
private void CheckTo()
{
if( creator )
{
return;
}
int realsize = ReceiveChangeMsg();
if( size < realsize)
{
Open( realsize,Name,curOffset,curAccess);
}
}
private void ReceiveChangeMsg(out int length)
{
length = ReceiveChangeMsg();
}
private int ReceiveChangeMsg()
{
string[] msgs = msgmem.CopyToString().Split( SpliteChar);
if( msgs.Length != 2 || msgs[0] != CHANGESIZE)
{
return 0;
}
return int.Parse( msgs[1]);
}
#endregion
#endregion
}
#endregion
注: 在CopyTo和CopyFrom前,都加入了一个检测函数.
CopyFrom前: 如果发现新的数据比申请的要大,就直接将原来的内存映射文件关掉,重新申请一个大的空间,同时修改MsgMem中的数据.
CopyTo前: 如果发现MsgMem中的消息为ChangeSize,而且新的Size大于当前的Size,就把当前的内存映射文件Release,再重新Open.
对于内存映射文件的创建者(用bool creator来标识),才可以重新Create,对于非创建者,才可以重新Open :)
希望大家喜欢:)
ps,代码就不用提供下载了吧??
...还是提供一个吧,最新的:)
SharedMemoryEx.zip