window应用程序靠消息驱动、Marshal类、StructureToByte、ByteToStructure

来源:互联网 发布:红外图像处理算法 编辑:程序博客网 时间:2024/05/29 02:47

1、BLE(BlueTooth Low energy)

2、System.Environment.TickCount属性获得系统启动后经过的毫秒数

WINDOWS应用程序是靠消息驱动的

3、Marshal类的整理

托管代码 (managed code) :由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,
例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。 
Unmanaged Code
非托管代码 :在公共语言运行库环境的外部,由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;
它与托管代码不同,后者从公共语言运行库中获得这些服务。非托管代码的英文名是Unmanaged Code ,它是在公共语言运行库环境的外部,
操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同,后者从公共语言运行库中
获得这些服务。

将数据从托管对象封送到非托管内存块,属于.NET Framework 类库
命名空间:System.Runtime.InteropServices
程序集:mscorlib(在 mscorlib.dll 中)

关于

在两个不同的实体(两个线程或者进程甚至机器、在Managed和Unmanaged之间)进行方法调用和参数传递的时候,具体的调用方法和参数的内存格式可能需要一定的转换,这个转换的过程叫做Marshal。

Marshal就是把一个结构(类)序列化成一段内存,然后送到另一个进程(.net中Application domain)中供另一个进程中的函数使用。
比如你的一个结构

struct

{
Pen pen;
}s; 

s是一个指向已有的Pen对象的引用,当你把s传给本进程中的一个函数f时,f可以很容易地找到pen的实际对象,但如果你把s传到另外一个进程时,甚至是另外一台机器上的进程时,这个进程就没办法找到pen的实际内容。Marshal技术则可以把pen对象中的所有实际内容按规则放到一个缓冲中,(所有的引用或指针都要转换成实际对象)然后把缓冲中的内容送到另一个进程,函数调用完成再用同样方式把结果返回来。
在RPC,Interop,COM中Marshal应用很多。

            int size = Marshal.SizeOf(cmd[0]) * cmd.Length;            IntPtr pnt = Marshal.AllocHGlobal(size);//在进程的非托管中内存中分配size大小的内存,内存的第一个字节地址为pnt            Marshal.Copy(cmd, 0, pnt, cmd.Length);//复制到pnt中             //其中H:heap  Global Allocate            Marshal.FreeHGlobal(pnt);//释放


4、

我们主要是使用Marshal类里的两个方法:第一个是StructureToPtr,将数据从托管对象封送到非托管内存块。第二个是PtrToStructure,将数据从非托管内存块封送到新分配的指定类型的托管对象。只要有了这两个相互转换的方法,我们就可以实现序列化了。首先我们先来看下序列化序列化:有一个前提条件,那就是我们必须要知道需要序列化对象的大小。第一步:我们先求出对象的大小,然后在非托管内存中给它分配相应的内存大小。第二步:接着我们就把这个对象封送到刚分配出来的内存中,之后我们会得到一个分配出来的内存块首地址指针。第三步:最后我们可以通过这个首地址指针,从指针所指的位置处开始,拷贝数据到指定的byte[]数组中,拷贝的长度就是我们为这个对象分配出来的内存大小,得到byte[]数据后,下面的事情我就不用多说了,你可以保存到数据库或者文件中。反序列化:序列化的时候我们先将一个对象封送到了非托管内存块中,然后再把内存块中的数据读到byte[]数组中,现在我们反序列化第一步:我们先求出对象的大小,然后在非托管内存中给它分配相应的内存大小。第二步:然后把这个byte[]数据拷贝到非托管内存块中。第三步:最后再从内存块中封送指定大小的数据到对象中。有一个地方需要注意,那就是因为引用类型的对象我们是无法求的它的实际大小的,所以这里的对象我们只能使用非托管对象,比如struct结构体。所以,当我们只是用来存储数据,不涉及任何操作的对象,我们可以把它作为一个结构体来处理,这样我们在序列化的时候可以节省空间开销。因为你如果你要是用平常的序列化方法去序列化一个类对象,他所需要的空间开销是要大于你去序列化一个具有相同结构的struct对象。下面是代码:

5、

public static class MyConverter{/// <summary>/// 由结构体转换为byte数组/// </summary>public static byte[] StructureToByte<T>(T structure){int size = Marshal.SizeOf(typeof(T));byte[] buffer = new byte[size];IntPtr bufferIntPtr = Marshal.AllocHGlobal(size);try{Marshal.StructureToPtr(structure, bufferIntPtr, true);Marshal.Copy(bufferIntPtr, buffer, 0, size);}finally{Marshal.FreeHGlobal(bufferIntPtr);}return buffer;}/// <summary>/// 由byte数组转换为结构体/// </summary>public static T ByteToStructure<T>(byte[] dataBuffer){object structure = null;int size = Marshal.SizeOf(typeof(T));IntPtr allocIntPtr = Marshal.AllocHGlobal(size);try{Marshal.Copy(dataBuffer, 0, allocIntPtr, size);structure = Marshal.PtrToStructure(allocIntPtr, typeof(T));}finally{Marshal.FreeHGlobal(allocIntPtr);}return (T)structure;}}

测试代码:

class Program{static void Main(string[] args){Student student1 = new Student { Name = "胡昌俊", ID = 2 };Console.WriteLine("序列化前=> 姓名:{0} ID:{1}", student1.ID, student1.Name);byte[] bytes = MyConverter.StructureToByte<Student>(student1);Student sudent2 = MyConverter.ByteToStructure<Student>(bytes);Console.WriteLine("序列化后=> 姓名:{0} ID:{1}", sudent2.ID, sudent2.Name);Console.Read();}}public struct Student{public int ID { get; set; }public string Name { get; set; }}




...