概述
首先定义一个基础消息结构体用于消息传递封包
/// <summary> /// 基础消息结构体 /// </summary> public struct WindowsLparamStruct { /// <summary> /// 是否释放大于0表示内存没有被释放 /// </summary> public int State; /// <summary> /// 指向被序列化对象的指针 /// </summary> public IntPtr BytePrt; /// <summary> /// 序列化对象的字节长度 /// </summary> public int Length; }
然后新建一个对象成员是调用SendMessage API
public class WindowApis { /// <summary> /// 自定义消息起始 /// </summary> public static int CunstomMessage = 0X400 + 2; /// <summary> /// 同步发送消息 /// </summary> /// <param name="hWnd"></param> /// <param name="msg"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <returns></returns> [DllImport("User32.dll", EntryPoint = "SendMessage")] public static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); /// <summary> /// 异步发送消息 /// </summary> /// <param name="hWnd"></param> /// <param name="Msg"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <returns></returns> [DllImport("User32.dll", EntryPoint = "PostMessage")] public static extern int PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); }
然后封装发送消息都类
public class WindowsMessageHandler { /// <summary> /// 构造函数 /// </summary> public WindowsMessageHandler() { }
//是否异步
private bool IsAsynchronous; /// <summary> /// 窗口句柄 /// </summary> public IntPtr WindowHandle; /// <summary> /// 窗体消息 /// </summary> public WindowsMessage WindMsg; /// <summary> /// 将对象序列化成BYTE数组 /// </summary> /// <param name="obj"></param> /// <returns></returns> private byte[] SeriObjectToBytes(object obj) { byte[] objBuffer = null; using (MemoryStream ms = new MemoryStream()) { //序列化操作,把内存中的东西写到硬盘中 BinaryFormatter fomatter = new BinaryFormatter(); fomatter.Serialize(ms, obj); objBuffer = ms.GetBuffer(); } return objBuffer; } /// <summary> /// 发送 /// </summary> /// <returns></returns> public override int Send() { return this.Send(this.WindowHandle, this.SendObject, this.WindMsg, this.IsAsynchronous); } /// <summary> /// 添加节点 /// </summary> /// <param name="nd"></param> private void PushBuffer(IntPtr objptr, IntPtr bufferptr) { BufferNode bn = new BufferNode(); bn.BufferPtr = bufferptr; bn.ObjectPtr = objptr; BufferNodes.Enqueue(bn); } /// <summary> /// 关闭BUFFER /// </summary> private void CleanBuffer() { while (BufferNodes.Count > 0) { BufferNode nd = BufferNodes.Dequeue(); Marshal.FreeHGlobal(nd.ObjectPtr); Marshal.FreeHGlobal(nd.BufferPtr); } } /// <summary> /// 将序列化成BYTE数组都对象拷贝到消息结构体 /// </summary> /// <param name="objBuffer"></param> /// <returns>返回消息结构体都指针</returns> private IntPtr BuildWslPtr(byte[] objBuffer) {
//第一步是把WindowsLparamStruct的BytePtr指针成员指向序列化之后的数组首地址并记录地址都大小 WindowsLparamStruct wls = new WindowsLparamStruct();//传送结构体 wls.Length = objBuffer.Length;//序列化对像数组长度 wls.BytePrt = Marshal.AllocHGlobal(objBuffer.Length);//开辟数组大小的空间 Marshal.Copy(objBuffer, 0, wls.BytePrt, wls.Length);//将序列化成BYTE数组的obj对象成员拷贝到结构体指针地址
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(wls));//给传送结构体指针分配obj对象大小的内存 Marshal.StructureToPtr(wls, ptr, true); //把结构体的拷贝到指针指指向的内存 this.PushBuffer(ptr, wls.BytePrt);//指针入队方便统一清理内存防止内存泄漏 return ptr;//返回传送结构体指针 } /// <summary> /// 发送结构体数据 /// </summary> /// <param name="windKey">窗口句柄</param> /// <param name="obj">需要发送的结构体</param> /// <param name="isAnaly">true表示异步否则同步</param> /// <returns></returns> private int Send(IntPtr handle, object obj, WindowsMessage msg, bool isAnaly = false) { int result = 0;//用于返回结果 IntPtr ptr = BuildWslPtr(SeriObjectToBytes(obj)); ptr = BuildWslPtr(SeriObjectToBytes(obj)); try { if (isAnaly == true) { result = WindowApis.PostMessage(handle, WindowApis.CunstomMessage, msg.ToPtr(), ptr); } else { result = WindowApis.SendMessage(handle, WindowApis.CunstomMessage, msg.ToPtr(), ptr); CleanBuffer();//同步情况下可以及时清理内存 } } catch (Exception ex) { result = -1;//出现异常返回-1 } finally { } return result; } }
新建测试对象
[Serializable] public class Mys { public Mys() { } public int j; public long i; public byte[] x; public string oo; }
最后是使用方法
WindowsMessageHandler wmh = new WindowsMessageHandler(); private void button1_Click(object sender, EventArgs e) { wmh.WindowHandle = this.Handle;//接受数据都窗体指针 wmh.WindMsg = new WindowsMessage("ads");//标记消息名 wmh.IsAsynchronous = false; ThreadPool.QueueUserWorkItem(new WaitCallback(ROC), 0); } //工作线程发送带有数组成员得对象 private void ROC(object obj) { for (int i = 0; i < 10000; i++) { Mys mys = new Mys(); mys.x = new byte[10000]; mys.oo = "00"; wmh.SendObject = mys; wmh.Send(); } }
接收端窗体消息过程
protected override void WndProc(ref System.Windows.Forms.Message msg) { if (WindowsMessageHelper.CUSTOM_MESSAGE == msg.Msg) { if (WindowsMessage.Equals(msg.WParam, "ads")) { WindowsLparamStruct res = (WindowsLparamStruct)Marshal.PtrToStructure(msg.LParam, typeof(WindowsLparamStruct)); byte[] resByte = new byte[res.Length];//新建序列化对象数组长度的空间 Marshal.Copy(res.BytePrt, resByte, 0, res.Length);//从指针地址把对象数组拷贝到新鲜都resBytes MemoryStream ms = new MemoryStream(resByte);//反序列化 ms.Position = 0; BinaryFormatter formatter = new BinaryFormatter(); Mys obj = (Mys)formatter.Deserialize(ms) } } base.WndProc(ref msg);//调用基类函数处理非自定义消息。 }
转载于:https://www.cnblogs.com/Isesame/p/11161493.html
最后
以上就是漂亮山水为你收集整理的C#如何使用SendMessage安全的跨线程,跨进程传递任意对象的全部内容,希望文章能够帮你解决C#如何使用SendMessage安全的跨线程,跨进程传递任意对象所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复