DllImport特性
在C#中,DllImport是一种特性,它被用于指定在本地代码中调用的DLL(动态链接库)的入口点。DllImport特性通常被应用于C#中的托管代码中,以便调用由C、C++或者其他非托管语言编写的DLL。 使用DllImport特性,你可以在C#中调用DLL中的函数,而不需要了解该DLL的内部实现细节。这使得C#能够与各种不同的外部库进行交互,并扩展了C#的功能。 ...
在C#中,DllImport是一种特性,它被用于指定在本地代码中调用的DLL(动态链接库)的入口点。DllImport特性通常被应用于C#中的托管代码中,以便调用由C、C++或者其他非托管语言编写的DLL。 使用DllImport特性,你可以在C#中调用DLL中的函数,而不需要了解该DLL的内部实现细节。这使得C#能够与各种不同的外部库进行交互,并扩展了C#的功能。 ...
线程安全是多线程编程时的计算机程序代码中的一个概念。 在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且准确的执行,不会出现数据污染等意外情况。 也就是说,如果我们想要确保在多线程访问的时候,程序还能够按照我们的预期的行为去执行,那么就是线程安全了。同时,线程安全也是一种内存安全,在没有保护机制的情况下,堆内存空间对多线程来说是不安全的地方,因为你放进去的数据,可能被别的线程“破坏”。
从Microsoft .Net 2.0版本以后,就默认提供了System.IO.Ports.SerialPort类,用户可以非常简单地编写少量代码就完成串口的信息收发程序。 串口端口号搜索 string[] portList = System.IO.Ports.SerialPort.GetPortNames(); for (int i = 0; i < portList.Length; i++) { string name = portList[i]; comboBox.Items.Add(name); } 串口属性参数设置 SerialPort mySerialPort = new SerialPort("COM2");//端口 mySerialPort.BaudRate = 9600;//波特率 mySerialPort.Parity = Parity.None;//校验位 mySerialPort.StopBits = StopBits.One;//停止位 mySerialPort.DataBits = 8;//数据位 mySerialPort.Handshake = Handshake.Non; mySerialPort.ReadTimeout = 1500; mySerialPort.DtrEnable = true;//启用数据终端就绪信息 mySerialPort.Encoding = Encoding.UTF8; mySerialPort.ReceivedBytesThreshold = 1;//DataReceived触发前内部输入缓冲器的字节数 mySerialPort.DataReceived += new SerialDataReceivedEvenHandler(DataReceive_Method); mySerialPort.Open(); 串口发送信息 // Write a string port.Write("Hello World"); // Write a set of bytes port.Write(new byte[] { 0x0A, 0xE2, 0xFF }, 0, 3); // Close the port port.Close(); 串口接收信息 string serialReadString; private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) { serialReadString = port.ReadExisting()); this.txt1.Invoke( new MethodInvoker(delegate { this.txt1.AppendText(serialReadString); })); } 循环接收数据 void com_DataReceived(object sender, SerialDataReceivedEventArgs e) { // Use either the binary OR the string technique (but not both) // Buffer and process binary data while (com.BytesToRead > 0) bBuffer.Add((byte)com.ReadByte()); ProcessBuffer(bBuffer); // Buffer string data sBuffer += com.ReadExisting(); ProcessBuffer(sBuffer); } private void ProcessBuffer(string sBuffer) { // Look in the string for useful information // then remove the useful data from the buffer } private void ProcessBuffer(List<byte> bBuffer) { // Look in the byte array for useful information // then remove the useful data from the buffer }
[STAThread] STAThread:Single Thread Apartment Thread.(单一线程单元线程) []是用来表示Attributes; [STAThread] 是一种线程模型,用在程序的入口方法上(在C#和VB.NET里是Main()方法),来指定当前线程的ApartmentState 是STA。用在其他方法上不产生影响。在aspx页面上可以使用AspCompat = “true” 来达到同样的效果。这个属性只在 Com Interop 有用,如果全部是 managed code 则无用。简单的说法:[STAThread]指示应用程序的默认线程模型是单线程单元 (STA)。启动线程模型可设置为单线程单元或多线程单元。如果未对其进行设置,则该线程不被初始化。也就是说如果你用的.NET Framework,并且没有使用COM Interop,一般不需要这个Attribute。其它的还有MTA(多线程套间)、Free Thread(自由线程)。 ...
使用快捷键:CTRL+SHIFT+L 示例:我们有下面多条链接,现在我们需要将链接中的181、182…数字找出来,并替换成110; 第一步:按下CTRL+F 并在右上角启用正则表达式 输入匹配规则(这一步在解决本文的问题中,并不重要,重要的是第二步) 第二步:点击界面空白处(这一步是为了不让光标还在搜索框中),按下CTRL+SHIFT+L 快捷键 当我们要批量操作目标字符串时:在完成了查找这个过程后,如何全部选中目标是我们最关心的,(CTRL+SHIFT+L帮我们解决了这个问题),至于选中后我们是"复制(CTRL+C)“还是直接批量修改便不是问题了。
.ctor 构造函数,在类被实例化时,它会被自动调用。 .cctor 类型初始化器,是一个静态方法,无参数无返回值,不能直接调用,最多只有一个 在继承中对象构造过程,看下面这段程序: public class A { public int x = 1; public A() { m1(); } public void m1() { } } public class B : A { public int y = 2; public static string sb = "B"; public B() { m2(); } public void m2() { } } public class C : B { public int z = 3; public static string sc = "C"; public C() { m3(); } public void m3() { } } 可以看到三者都有一个.ctor,B、C中有.cctor,而A没有,打开B,C的.cctor,可以看到它们都负责初始化自己的静态字段,现在主要来看它们的.ctor。 ...
在不同的解决方案中把一个项目搬来搬去,终于出现了传说的CSC : error CS0006。 编译的时候总是提示一个引用中不存在的项找不到元数据文件。 无论怎样删除项目,删除引用都没法通过生成。 解决方案 找到自己的xxx.csproj项目文件 以文本的方式打开改文件 找到包含出问题的引用项所在的项,整个删除此项。
析构函数 析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。 ...
Platform Invoke(P/Invoke),即平台调用,主要用于调用C库函数和Windows API using System; // 使用平台调用技术进行互操作性之前,首先需要添加这个命名空间 using System.Runtime.InteropServices; namespace 平台调用Demo { class Program { // 在托管代码中对非托管函数进行声明,并且附加平台调用所需要属性 // 在默认情况下,CharSet为CharSet.Ansi // 指定调用哪个版本的方法有两种——通过DllImport属性的CharSet字段和通过EntryPoint字段指定 // 在托管函数中声明注意一定要加上 static 和extern 这两个关键字 [DllImport("user32.dll")] public static extern int MessageBox1(IntPtr hWnd, String text, String caption, uint type); // 在默认情况下,CharSet为CharSet.Ansi [DllImport("user32.dll")] public static extern int MessageBoxA(IntPtr hWnd, String text, String caption, uint type); // 在默认情况下,CharSet为CharSet.Ansi [DllImport("user32.dll")] public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type); // 第一种指定方式,通过CharSet字段指定 [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern int MessageBox2(IntPtr hWnd, String text, String caption, uint type); // 通过EntryPoint字段指定 [DllImport("user32.dll", EntryPoint="MessageBoxA")] public static extern int MessageBox3(IntPtr hWnd, String text, String caption, uint type); [DllImport("user32.dll", EntryPoint = "MessageBoxW")] public static extern int MessageBox4(IntPtr hWnd, String text, String caption, uint type); static void Main(string[] args) { // 在托管代码中直接调用声明的托管函数 // 使用CharSet字段指定的方式,要求在托管代码中声明的函数名必须与非托管函数名一样 // 否则就会出现找不到入口点的运行时错误 //MessageBox1(new IntPtr(0), "Learning Hard", "欢迎", 0); // 下面的调用都可以运行正确 //MessageBoxA(new IntPtr(0), "Learning Hard", "欢迎", 0); //MessageBox(new IntPtr(0), "Learning Hard", "欢迎", 0); // 使用指定函数入口点的方式调用 //MessageBox3(new IntPtr(0), "Learning Hard", "欢迎", 0); // 调用Unicode版本的会出现乱码 MessageBox4(new IntPtr(0), "Learning Hard", "欢迎", 0); } } } C++ Introp, 主要用于Managed C++(托管C++)中调用C++类库 第二部分主要向大家介绍了第一种互操作性技术,然后我们也可以使用C++ Interop技术来实现与非托管代码进行交互。 然而C++ Interop 方式有一个与平台调用不一样的地方,就是C++ Interop 允许托管代码和非托管代码存在于一个程序集中,甚至同一个文件中。 C++ Interop 是在源代码上直接链接和编译非托管代码来实现与非托管代码进行互操作的,而平台调用是加载编译后生成的非托管DLL并查找函数的入口地址来实现与非托管函数进行互操作的。 C++ Interop使用托管C++来包装非托管C++代码,然后编译生成程序集,然后再托管代码中引用该程序集,从而来实现与非托管代码的互操作。 ...
在Window窗體程式開發的時候,如果使用多執行緒程式設計,在子執行緒中訪問主執行緒窗體內的控制元件,就需要使用控制元件的Control.Invoke方法或者BeginInvoke方法。但是有時候因為Window執行速度太快,尤其是你寫程式碼的時候在InitializeComponent();完成之前起了一個執行緒去執行某些操作,涉及到窗體控制元件的,當你在呼叫Control.Invoke的時候,就可能出現 “在建立視窗控制代碼之前,不能在控制元件上呼叫 Invoke 或 BeginInvoke ...