Sun, September 12, 2004, 05:16 PM under
MobileAndEmbedded
Continuing from
previous entry on IPC options with Compact Framework there are only two left - they are very similar.
7. Named Events + registry
8. Directly Share memory
7. For simple data sharing, it is easy for an app to write data to predefined regisrty entries and signal a named event; at that point the other side can read from the registry. It looks something like this:
// SERVER PROCESS
//write data
private void cmdWrite_Click(object sender, System.EventArgs e) {
IntPtr hWnd = Win32Api.CreateEvent(IntPtr.Zero, true,
false, "YOUR_NAME_HERE");
// TODO write to reg
//e.g. with opennetcf Registry class
Win32Api.SetEvent(hWnd);
System.Threading.Thread.Sleep(500);
Win32Api.CloseHandle(hWnd);
}
// CLIENT PROCESS
private System.Threading.Thread mMonitorThread;
private bool mStayAlive;
private IntPtr mMonitorHwnd;
//read data
private void cmdRead_Click(object sender, System.EventArgs e) {
mStayAlive = true;
mMonitorHwnd = Win32Api.CreateEvent(IntPtr.Zero, true,
false, "YOUR_NAME_HERE");
mMonitorThread = new System.Threading.Thread(
new System.Threading.ThreadStart(
this.MonitorOtherProc));
mMonitorThread.Start();
}
// on background thread so make sure we don't
// touch GUI controls from here
private void MonitorOtherProc(){
while (mStayAlive){
Win32Api.WaitForSingleObject(mMonitorHwnd, -1);
if (mStayAlive == false) return;
MessageBox.Show("Got data "+
DateTime.Now.ToString(), "TODO read from reg");
// TODO read data from reg
Win32Api.ResetEvent(mMonitorHwnd);
}
}
// must call this before closing app - e.g. from Form_Closing
public void Shutdown(){
if (mMonitorThread == null) return;
mStayAlive = false;
Win32Api.SetEvent( mMonitorHwnd);
System.Threading.Thread.Sleep(500);
Win32Api.CloseHandle( mMonitorHwnd);
mMonitorThread = null;
}
8. Directly sharing memory is not advisable but we can do it. The logic is identical to case 7 with named events but instead of writing/reading from registry, we access memory directly. It looks something like this:
// BOTH CLIENT & SERVER PROCESS NEED THESE
// Returns pointer to shared memory
private IntPtr ObtainHandleToSharedMemory(){
const uint PHYS_ADDR =0x80230000;//Make sure this is not used
on your platform
const int MEM_SIZE = 10;
IntPtr hwnd =
Win32Api.VirtualAlloc(0, MEM_SIZE, Win32Api.MEM_RESERVE,
Win32Api.PAGE_READWRITE|Win32Api.PAGE_NOCACHE);
if (hwnd.ToInt32() != 0){
if (Win32Api.VirtualCopy(hwnd, PHYS_ADDR, MEM_SIZE,
(Win32Api.PAGE_READWRITE|Win32Api.PAGE_NOCACHE))
== true){
return hwnd;
}
}
MessageBox.Show(
Marshal.GetLastWin32Error().ToString(),"Failed");
return IntPtr.Zero;
}
// Define common structure/class in both client and server e.g.
private class SharedMemory{
public byte b1;
public byte b2;
public char c;
public bool flag;
public int i;
public SharedMemory(bool aFlag){
flag=aFlag;
if (aFlag){
b1=1;b2=2;c='!';i=3;
}else{
b1=0;b2=0;c=' ';i=0;
}
}
public override string ToString() {
return "b1=" + b1.ToString() + ", b2="+b2.ToString()
+ ", c=" + c + ", i=" + i.ToString();
}
}
// CLIENT
// As in previous example but instead of reading the registry
// read the following in MonitorOtherProc
IntPtr memHwnd=ObtainHandleToSharedMemory();
if (memHwnd.ToInt32() !=0 ){
SharedMemory sm=new SharedMemory(false);
Marshal.PtrToStructure(memHwnd,sm);
MessageBox.Show(sm.ToString(),sm.flag.ToString());
}
// SERVER
// As in previous example but instead of writing to registry
// do the following in cmdWrite_Click
IntPtr memHwnd=ObtainHandleToSharedMemory();
if (memHwnd.ToInt32() !=0 ){
SharedMemory sm=new SharedMemory(true);
Marshal.StructureToPtr(sm,memHwnd,false);
}