有一个服务进程S,它包含大量的数据,系统中还有另外几个进程,定义为:进程a,进程b,进程c
现在进程a、b、c都要对服务进程S进行访问,且进行数据的读写交互,且保证每个进程当前读S进程的数据是最新的。
我个人认为进程S需要开辟一块内存区域,且进程a,b,c都要对该内存进行访问和数据的通信。
但是C#如何开辟内存呢?进程之间是怎么通信的呢?有如何保证每个进程得到的服务进程的数据都是最新的呢?
网上也查了一些资料,搞得一头雾水,请牛人们给些指点,谢谢!
现在进程a、b、c都要对服务进程S进行访问,且进行数据的读写交互,且保证每个进程当前读S进程的数据是最新的。
我个人认为进程S需要开辟一块内存区域,且进程a,b,c都要对该内存进行访问和数据的通信。
但是C#如何开辟内存呢?进程之间是怎么通信的呢?有如何保证每个进程得到的服务进程的数据都是最新的呢?
网上也查了一些资料,搞得一头雾水,请牛人们给些指点,谢谢!
其实更简单的方法,是webservice,wcf或remoting
C#实现可以参考 :
http://blog.csdn.net/yefanqiu/article/details/1717458
还有就是这三个线程同属于一个应用程序
可以使用进程继承,DuplicateHandle进程句柄复制,还有个命名对象。。按照LZ的需求,后两者最合适
多线程的话直接可以用Invoke或者delegate等多进程的话涉及到windows的消息机制
下面是一段接收端简单示例,基本上就是这样 protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
//your process
break;
default:
base.DefWndProc(ref m);
break;
}
}
后者可以PInvoke该DuplicateHandle函数,至于函数详细可以参阅MSDN
命名对象比如Semphore,Mutex,Monitor...都可以
问题二:进程间通讯我比较习惯用的是windows Message。至于数据最新,这个你自己设计相关逻辑去更新你服务进程中的数据。给你一个winMsg例子做参考Server发送数据private static void YourSendMessage(string strSendingData)
{
//调用发送消息方法
sendMessage(strSendingData);
} const int WM_COPYDATA = 0x004A; //发送消息
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(
int hWnd,
int Msg,
int wParam,
ref COPYDATASTRUCT lParam
);
//通过窗口标题找到窗口
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern int FindWindow(string lpClassName, string lpWindowName);
public static void sendMessage(string strSendingMsg)
{
string winName = ""; //你想要发送的窗口标题
int window_handler = FindWindow(null, @winName);
if (window_handler != 0)
{
byte[] byt = System.Text.Encoding.Default.GetBytes(strSendingMsg);
int len = byt.Length;
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)100;
cds.lpdata = strSendingMsg;
cds.cbData = len + 1; SendMessage(window_handler, WM_COPYDATA, 0, ref cds);
}
} public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpdata;
}
Client接收数据const int WM_COPYDATA = 0x004A;
#region 消息机制数据载体
//数据载体
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
#endregion #region 消息机制
//窗体接收windows消息的方法
protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
//your process
break;
default:
base.DefWndProc(ref m);
break;
}
}
#endregion
C#操作类似于C++中的句柄(非windowsForm句柄)如何实现?
编译通过后,先运行多个例子,看看互相之间的交互结果。其中MemoryMappedFile为共享内存,Mutex用来进行同步,ManualResetEvent用来通知有新的更新。
更新通知很初级但基本有效,我有时间再作进一步解释。class Program
{
static void Main()
{
new Program().Run();
} void Run()
{
ThreadPool.QueueUserWorkItem(this.Observer); string line;
while ((line = Console.ReadLine()) != "")
{
Console.CursorTop = Console.CursorLeft = 0;
Console.Write(new string(' ', 80));
Console.CursorTop = Console.CursorLeft = 0; PutString(line);
}
} List<string> lines = new List<string>();
void DisplayLines()
{
Console.CursorTop = Console.CursorLeft = 0;
Console.WriteLine(Environment.NewLine);
Console.ForegroundColor = ConsoleColor.DarkGreen;
foreach (string line in lines)
{
Console.WriteLine(line);
}
Console.ForegroundColor = ConsoleColor.Gray;
Console.CursorTop = Console.CursorLeft = 0;
} void Observer(object state)
{
int lastOffset = sizeof(int);
while (true)
{
notifyEvent.WaitOne();
if (GetStrings(ref lastOffset) == false)
{
Thread.Sleep(50);
}
}
} void PutString(object state)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(state as string);
try
{
mutex.WaitOne();
using (MemoryMappedViewAccessor accessor = memMap.CreateViewAccessor())
{
int offset = accessor.ReadInt32(0); offset = Math.Max(sizeof(int), offset);
accessor.Write(offset, (int)bytes.Length); offset += sizeof(int);
accessor.WriteArray<byte>(offset, bytes, 0, bytes.Length); offset += bytes.Length;
accessor.Write(0, offset);
}
}
finally
{
mutex.ReleaseMutex();
}
notifyEvent.Set();
Thread.Sleep(100);
notifyEvent.Reset();
} bool GetStrings(ref int lastOffset)
{
try
{
mutex.WaitOne();
using (MemoryMappedViewAccessor accessor = memMap.CreateViewAccessor())
{
int newOffset = accessor.ReadInt32(0);
if (newOffset <= lastOffset) return false; for (int offset = lastOffset; offset < newOffset; )
{
int stringLength = accessor.ReadInt32(offset); offset += sizeof(int); byte[] bytes = new byte[stringLength];
accessor.ReadArray<byte>(offset, bytes, 0, bytes.Length); offset += stringLength; this.lines.Add(Encoding.UTF8.GetString(bytes));
}
lastOffset = newOffset;
}
}
finally
{
mutex.ReleaseMutex();
}
DisplayLines();
return true;
} Mutex mutex = new Mutex(false, "MyMutex");
MemoryMappedFile memMap = MemoryMappedFile.CreateOrOpen("MyMemoryMap", 64 * 1024);
EventWaitHandle notifyEvent = new EventWaitHandle(false, EventResetMode.ManualReset, "MyNotifyEvent");
}