本文主要是講述如何通過C# .net1.1平台調用API操作串口,.net2.0已經內置串口操作類! 通常,在C#中實現串口通信,我們有四種方法: 第一:通過MSCOMM控件這是最簡單的,最方便的方法。可功能上很難做到控制自如,同時這個控件並不是系統本身所帶,所以還得注冊。可以訪問 http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=320 一個外國人寫的教程 第二:微軟在.NET新推出了一個串口控件,基於.NET的P/Invoke調用方法實現,詳細的可以訪問微軟網站 Serial Comm Use P/Invoke to Develop a .NET Base Class Library for Serial Device Communications http://msdn.microsoft.com/msdnmag/issues/02/10/netserialcomm/ 第三:就是用第三方控件啦,可一般都要付費的,不太合實際,何況樓主不喜歡,不作考慮 第四:自己用API寫串口通信,這樣難度高點,但對於我們來說,可以方便實現自己想要的各種功能。 我們采用第四種方法來實現串口通信,用現成的已經封裝好的類庫,常見兩個串口操作類是JustinIO和SerialStreamReader。介紹JustinIO的使用方法: 打開串口: 函數原型:public void Open() 說明:打開事先設置好的端口 示例: [csharp] view plaincopyprint?using JustinIO; static JustinIO.CommPort ss_port = new JustinIO.CommPort(); ss_port.PortNum = COM1; //端口號 ss_port.BaudRate = 19200; //串口通信波特率 ss_port.ByteSize = 8; //數據位 ss_port.Parity = 0; //奇偶校驗 ss_port.StopBits = 1;//停止位 ss_port.ReadTimeout = 1000; //讀超時 try { if (ss_port.Opened) { ss_port.Close(); ss_port.Open(); //打開串口 } else { ss_port.Open();//打開串口 } return true; } catch(Exception e) { MessageBox.Show("錯誤:" + e.Message); return false; } using JustinIO; static JustinIO.CommPort ss_port = new JustinIO.CommPort(); ss_port.PortNum = COM1; //端口號 ss_port.BaudRate = 19200; //串口通信波特率 ss_port.ByteSize = 8; //數據位 ss_port.Parity = 0; //奇偶校驗 ss_port.StopBits = 1;//停止位 ss_port.ReadTimeout = 1000; //讀超時 try { if (ss_port.Opened) { ss_port.Close(); ss_port.Open(); //打開串口 } else { ss_port.Open();//打開串口 } return true; } catch(Exception e) { MessageBox.Show("錯誤:" + e.Message); return false; } 寫串口: 函數原型:public void Write(byte[] WriteBytes) WriteBytes 就是你的寫入的字節,注意,字符串要轉換成字節數組才能進行通信 示例: ss_port.Write(Encoding.ASCII.GetBytes("AT+CGMI\r")); //獲取手機品牌 讀串口: 函數原型:public byte[] Read(int NumBytes) NumBytes 讀入緩存數,注意讀取來的是字節數組,要實際應用中要進行字符轉換 示例: string response = Encoding.ASCII.GetString(ss_port.Read(128)); //讀取128個字節緩存 關閉串口: 函數原型:ss_port.Close() 示例: ss_port.Close(); 整合代碼: [csharp] view plaincopyprint?using System; using System.Runtime.InteropServices; namespace JustinIO { class CommPort { public int PortNum; public int BaudRate; public byte ByteSize; public byte Parity; // 0-4=no,odd,even,mark,space public byte StopBits; // 0,1,2 = 1, 1.5, 2 public int ReadTimeout; //comm port win32 file handle private int hComm = -1; public bool Opened = false; //win32 api constants private const uint GENERIC_READ = 0x80000000; private const uint GENERIC_WRITE = 0x40000000; private const int OPEN_EXISTING = 3; private const int INVALID_HANDLE_VALUE = -1; [StructLayout(LayoutKind.Sequential)] public struct DCB { //taken from c struct in platform sdk public int DCBlength; // sizeof(DCB) public int BaudRate; // current baud rate /* these are the c struct bit fields, bit twiddle flag to set public int fBinary; // binary mode, no EOF check public int fParity; // enable parity checking public int fOutxCtsFlow; // CTS output flow control public int fOutxDsrFlow; // DSR output flow control public int fDtrControl; // DTR flow control type public int fDsrSensitivity; // DSR sensitivity public int fTXContinueOnXoff; // XOFF continues Tx public int fOutX; // XON/XOFF out flow control public int fInX; // XON/XOFF in flow control public int fErrorChar; // enable error replacement public int fNull; // enable null stripping public int fRtsControl; // RTS flow control public int fAbortOnError; // abort on error public int fDummy2; // reserved */ public uint flags; public ushort wReserved; // not currently used public ushort XonLim; // transmit XON threshold public ushort XoffLim; // transmit XOFF threshold public byte ByteSize; // number of bits/byte, 4-8 public byte Parity; // 0-4=no,odd,even,mark,space public byte StopBits; // 0,1,2 = 1, 1.5, 2 public char XonChar; // Tx and Rx XON character public char XoffChar; // Tx and Rx XOFF character public char ErrorChar; // error replacement character public char EofChar; // end of input character public char EvtChar; // received event character public ushort wReserved1; // reserved; do not use } [StructLayout(LayoutKind.Sequential)] private struct COMMTIMEOUTS { public int ReadIntervalTimeout; public int ReadTotalTimeoutMultiplier; public int ReadTotalTimeoutConstant; public int WriteTotalTimeoutMultiplier; public int WriteTotalTimeoutConstant; } [StructLayout(LayoutKind.Sequential)] private struct OVERLAPPED { public int Internal; public int InternalHigh; public int Offset; public int OffsetHigh; public int hEvent; } [DllImport("kernel32.dll")] private static extern int CreateFile( string lpFileName, // file name uint dwDesiredAccess, // access mode int dwShareMode, // share mode int lpSecurityAttributes, // SD int dwCreationDisposition, // how to create int dwFlagsAndAttributes, // file attributes int hTemplateFile // handle to template file ); [DllImport("kernel32.dll")] private static extern bool GetCommState( int hFile, // handle to communications device ref DCB lpDCB // device-control block ); [DllImport("kernel32.dll")] private static extern bool BuildCommDCB( string lpDef, // device-control string ref DCB lpDCB // device-control block ); [DllImport("kernel32.dll")] private static extern bool SetCommState( int hFile, // handle to communications device ref DCB lpDCB // device-control block ); [DllImport("kernel32.dll")] private static extern bool GetCommTimeouts( int hFile, // handle to comm device ref COMMTIMEOUTS lpCommTimeouts // time-out values ); [DllImport("kernel32.dll")] private static extern bool SetCommTimeouts( int hFile, // handle to comm device ref COMMTIMEOUTS lpCommTimeouts // time-out values ); [DllImport("kernel32.dll")] private static extern bool ReadFile( int hFile, // handle to file byte[] lpBuffer, // data buffer int nNumberOfBytesToRead, // number of bytes to read ref int lpNumberOfBytesRead, // number of bytes read ref OVERLAPPED lpOverlapped // overlapped buffer ); [DllImport("kernel32.dll")] private static extern bool WriteFile( int hFile, // handle to file byte[] lpBuffer, // data buffer int nNumberOfBytesToWrite, // number of bytes to write ref int lpNumberOfBytesWritten, // number of bytes written ref OVERLAPPED lpOverlapped // overlapped buffer ); [DllImport("kernel32.dll")] private static extern bool CloseHandle( int hObject // handle to object ); [DllImport("kernel32.dll")] private static extern uint GetLastError(); public void Open() { DCB dcbCommPort = new DCB(); COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS(); // OPEN THE COMM PORT. hComm = CreateFile("COM" + PortNum ,GENERIC_READ | GENERIC_WRITE,0, 0,OPEN_EXISTING,0,0); // IF THE PORT CANNOT BE OPENED, BAIL OUT. if(hComm == INVALID_HANDLE_VALUE) { throw(new ApplicationException("Comm Port Can Not Be Opened")); } // SET THE COMM TIMEOUTS. GetCommTimeouts(hComm,ref ctoCommPort); ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout; ctoCommPort.ReadTotalTimeoutMultiplier = 0; ctoCommPort.WriteTotalTimeoutMultiplier = 0; ctoCommPort.WriteTotalTimeoutConstant = 0; SetCommTimeouts(hComm,ref ctoCommPort); // SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS. GetCommState(hComm, ref dcbCommPort); dcbCommPort.BaudRate=BaudRate; dcbCommPort.flags=0; //dcb.fBinary=1; dcbCommPort.flags|=1; if (Parity>0) { //dcb.fParity=1 dcbCommPort.flags|=2; } dcbCommPort.Parity=Parity; dcbCommPort.ByteSize=ByteSize; dcbCommPort.StopBits=StopBits; if (!SetCommState(hComm, ref dcbCommPort)) { //uint ErrorNum=GetLastError(); throw(new ApplicationException("Comm Port Can Not Be Opened")); } //unremark to see if setting took correctly //DCB dcbCommPort2 = new DCB(); //GetCommState(hComm, ref dcbCommPort2); Opened = true; } public void Close() { if (hComm!=INVALID_HANDLE_VALUE) { CloseHandle(hComm); } } public byte[] Read(int NumBytes) { byte[] BufBytes; byte[] OutBytes; BufBytes = new byte[NumBytes]; if (hComm!=INVALID_HANDLE_VALUE) { OVERLAPPED ovlCommPort = new OVERLAPPED(); int BytesRead=0; ReadFile(hComm,BufBytes,NumBytes,ref BytesRead,ref ovlCommPort); OutBytes = new byte[BytesRead]; Array.Copy(BufBytes,OutBytes,BytesRead); } else { throw(new ApplicationException("Comm Port Not Open")); } return OutBytes; } public void Write(byte[] WriteBytes) { if (hComm!=INVALID_HANDLE_VALUE) { OVERLAPPED ovlCommPort = new OVERLAPPED(); int BytesWritten = 0; WriteFile(hComm,WriteBytes,WriteBytes.Length,ref BytesWritten,ref ovlCommPort); } else { throw(new ApplicationException("Comm Port Not Open")); } } } } } using System; using System.Runtime.InteropServices; namespace JustinIO { class CommPort { public int PortNum; public int BaudRate; public byte ByteSize; public byte Parity; // 0-4=no,odd,even,mark,space public byte StopBits; // 0,1,2 = 1, 1.5, 2 public int ReadTimeout; //comm port win32 file handle private int hComm = -1; public bool Opened = false; //win32 api constants private const uint GENERIC_READ = 0x80000000; private const uint GENERIC_WRITE = 0x40000000; private const int OPEN_EXISTING = 3; private const int INVALID_HANDLE_VALUE = -1; [StructLayout(LayoutKind.Sequential)] public struct DCB { //taken from c struct in platform sdk public int DCBlength; // sizeof(DCB) public int BaudRate; // current baud rate /* these are the c struct bit fields, bit twiddle flag to set public int fBinary; // binary mode, no EOF check public int fParity; // enable parity checking public int fOutxCtsFlow; // CTS output flow control public int fOutxDsrFlow; // DSR output flow control public int fDtrControl; // DTR flow control type public int fDsrSensitivity; // DSR sensitivity public int fTXContinueOnXoff; // XOFF continues Tx public int fOutX; // XON/XOFF out flow control public int fInX; // XON/XOFF in flow control public int fErrorChar; // enable error replacement public int fNull; // enable null stripping public int fRtsControl; // RTS flow control public int fAbortOnError; // abort on error public int fDummy2; // reserved */ public uint flags; public ushort wReserved; // not currently used public ushort XonLim; // transmit XON threshold public ushort XoffLim; // transmit XOFF threshold public byte ByteSize; // number of bits/byte, 4-8 public byte Parity; // 0-4=no,odd,even,mark,space public byte StopBits; // 0,1,2 = 1, 1.5, 2 public char XonChar; // Tx and Rx XON character public char XoffChar; // Tx and Rx XOFF character public char ErrorChar; // error replacement character public char EofChar; // end of input character public char EvtChar; // received event character public ushort wReserved1; // reserved; do not use } [StructLayout(LayoutKind.Sequential)] private struct COMMTIMEOUTS { public int ReadIntervalTimeout; public int ReadTotalTimeoutMultiplier; public int ReadTotalTimeoutConstant; public int WriteTotalTimeoutMultiplier; public int WriteTotalTimeoutConstant; } [StructLayout(LayoutKind.Sequential)] private struct OVERLAPPED { public int Internal; public int InternalHigh; public int Offset; public int OffsetHigh; public int hEvent; } [DllImport("kernel32.dll")] private static extern int CreateFile( string lpFileName, // file name uint dwDesiredAccess, // access mode int dwShareMode, // share mode int lpSecurityAttributes, // SD int dwCreationDisposition, // how to create int dwFlagsAndAttributes, // file attributes int hTemplateFile // handle to template file ); [DllImport("kernel32.dll")] private static extern bool GetCommState( int hFile, // handle to communications device ref DCB lpDCB // device-control block ); [DllImport("kernel32.dll")] private static extern bool BuildCommDCB( string lpDef, // device-control string ref DCB lpDCB // device-control block ); [DllImport("kernel32.dll")] private static extern bool SetCommState( int hFile, // handle to communications device ref DCB lpDCB // device-control block ); [DllImport("kernel32.dll")] private static extern bool GetCommTimeouts( int hFile, // handle to comm device ref COMMTIMEOUTS lpCommTimeouts // time-out values ); [DllImport("kernel32.dll")] private static extern bool SetCommTimeouts( int hFile, // handle to comm device ref COMMTIMEOUTS lpCommTimeouts // time-out values ); [DllImport("kernel32.dll")] private static extern bool ReadFile( int hFile, // handle to file byte[] lpBuffer, // data buffer int nNumberOfBytesToRead, // number of bytes to read ref int lpNumberOfBytesRead, // number of bytes read ref OVERLAPPED lpOverlapped // overlapped buffer ); [DllImport("kernel32.dll")] private static extern bool WriteFile( int hFile, // handle to file byte[] lpBuffer, // data buffer int nNumberOfBytesToWrite, // number of bytes to write ref int lpNumberOfBytesWritten, // number of bytes written ref OVERLAPPED lpOverlapped // overlapped buffer ); [DllImport("kernel32.dll")] private static extern bool CloseHandle( int hObject // handle to object ); [DllImport("kernel32.dll")] private static extern uint GetLastError(); public void Open() { DCB dcbCommPort = new DCB(); COMMTIMEOUTS ctoCommPort = new COMMTIMEOUTS(); // OPEN THE COMM PORT. hComm = CreateFile("COM" + PortNum ,GENERIC_READ | GENERIC_WRITE,0, 0,OPEN_EXISTING,0,0); // IF THE PORT CANNOT BE OPENED, BAIL OUT. if(hComm == INVALID_HANDLE_VALUE) { throw(new ApplicationException("Comm Port Can Not Be Opened")); } // SET THE COMM TIMEOUTS. GetCommTimeouts(hComm,ref ctoCommPort); ctoCommPort.ReadTotalTimeoutConstant = ReadTimeout; ctoCommPort.ReadTotalTimeoutMultiplier = 0; ctoCommPort.WriteTotalTimeoutMultiplier = 0; ctoCommPort.WriteTotalTimeoutConstant = 0; SetCommTimeouts(hComm,ref ctoCommPort); // SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS. GetCommState(hComm, ref dcbCommPort); dcbCommPort.BaudRate=BaudRate; dcbCommPort.flags=0; //dcb.fBinary=1; dcbCommPort.flags|=1; if (Parity>0) { //dcb.fParity=1 dcbCommPort.flags|=2; } dcbCommPort.Parity=Parity; dcbCommPort.ByteSize=ByteSize; dcbCommPort.StopBits=StopBits; if (!SetCommState(hComm, ref dcbCommPort)) { //uint ErrorNum=GetLastError(); throw(new ApplicationException("Comm Port Can Not Be Opened")); } //unremark to see if setting took correctly //DCB dcbCommPort2 = new DCB(); //GetCommState(hComm, ref dcbCommPort2); Opened = true; } public void Close() { if (hComm!=INVALID_HANDLE_VALUE) { CloseHandle(hComm); } } public byte[] Read(int NumBytes) { byte[] BufBytes; byte[] OutBytes; BufBytes = new byte[NumBytes]; if (hComm!=INVALID_HANDLE_VALUE) { OVERLAPPED ovlCommPort = new OVERLAPPED(); int BytesRead=0; ReadFile(hComm,BufBytes,NumBytes,ref BytesRead,ref ovlCommPort); OutBytes = new byte[BytesRead]; Array.Copy(BufBytes,OutBytes,BytesRead); } else { throw(new ApplicationException("Comm Port Not Open")); } return OutBytes; } public void Write(byte[] WriteBytes) { if (hComm!=INVALID_HANDLE_VALUE) { OVERLAPPED ovlCommPort = new OVERLAPPED(); int BytesWritten = 0; WriteFile(hComm,WriteBytes,WriteBytes.Length,ref BytesWritten,ref ovlCommPort); } else { throw(new ApplicationException("Comm Port Not Open")); } } } } } C#中使用SerialPort類實現串口通信 在.NET Framework 2.0中提供了SerialPort類,該類主要實現串口數據通信等。本文章將本人在學習過程中從網絡上搜集到的相關信息寫出來供大家參考。 下面主要介紹該類的主要屬性(表1)和方法(表.2)。 如果需要了解更多的信息請登錄http://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport(VS.80).aspx查看。 相關文章 《使用System.IO.Ports讀取COM口數據》 http://www.devasp.net/net/articles/display/727.html 表1 SerialPort類的常用屬性 名 稱 說 明 BaseStream 獲取 SerialPort 對象的基礎 Stream 對象 BaudRate 獲取或設置串行波特率 BreakState 獲取或設置中斷信號狀態 BytesToRead 獲取接收緩沖區中數據的字節數 BytesToWrite 獲取發送緩沖區中數據的字節數 CDHolding 獲取端口的載波檢測行的狀態 CtsHolding 獲取“可以發送”行的狀態 DataBits 獲取或設置每個字節的標准數據位長度 DiscardNull 獲取或設置一個值,該值指示 Null 字節在端口和接收緩沖區之間傳輸時是否被忽略 DsrHolding 獲取數據設置就緒 (DSR) 信號的狀態 DtrEnable 獲取或設置一個值,該值在串行通信過程中啟用數據終端就緒 (DTR) 信號 Encoding 獲取或設置傳輸前后文本轉換的字節編碼 Handshake 獲取或設置串行端口數據傳輸的握手協議 IsOpen 獲取一個值,該值指示 SerialPort 對象的打開或關閉狀態 NewLine 獲取或設置用於解釋 ReadLine( )和WriteLine( )方法調用結束的值 Parity 獲取或設置奇偶校驗檢查協議 續表 名 稱 說 明 ParityReplace 獲取或設置一個字節,該字節在發生奇偶校驗錯誤時替換數據流中的無效字節 PortName 獲取或設置通信端口,包括但不限於所有可用的 COM 端口 ReadBufferSize 獲取或設置 SerialPort 輸入緩沖區的大小 ReadTimeout 獲取或設置讀取操作未完成時發生超時之前的毫秒數 ReceivedBytesThreshold 獲取或設置 DataReceived 事件發生前內部輸入緩沖區中的字節數 RtsEnable 獲取或設置一個值,該值指示在串行通信中是否啟用請求發送 (RTS) 信號 StopBits 獲取或設置每個字節的標准停止位數 WriteBufferSize 獲取或設置串行端口輸出緩沖區的大小 WriteTimeout 獲取或設置寫入操作未完成時發生超時之前的毫秒數 表2 SerialPort類的常用方法 方 法 名 稱 說 明 Close 關閉端口連接,將 IsOpen 屬性設置為False,並釋放內部 Stream 對象 Open 打開一個新的串行端口連接 Read 從 SerialPort 輸入緩沖區中讀取 ReadByte 從 SerialPort 輸入緩沖區中同步讀取一個字節 ReadChar 從 SerialPort 輸入緩沖區中同步讀取一個字符 ReadLine 一直讀取到輸入緩沖區中的 NewLine 值 ReadTo 一直讀取到輸入緩沖區中指定 value 的字符串 Write 已重載。將數據寫入串行端口輸出緩沖區 WriteLine 將指定的字符串和 NewLine 值寫入輸出緩沖區 使用SerialPort類的方法: 方法一: 首先要添加 using System.IO; using System.IO.Ports; 1...在類的內部定義SerialPort com; 2...打開串口 com = new SerialPort(); com.BaudRate = 115200; com.PortName = "COM1"; com.DataBits = 8; com.Open();//打開串口 3...發送數據 Byte[] TxData ={1,2,3,4,5,6,7,8 }; com.Write(TxData, 0, 8); 4...接收數據 4.1使用事件接收 this.com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.OnDataReceived); private void OnDataReceived(object sender, SerialDataReceivedEventArgs e) 4.2使用線程接收 接收數據啟動一個線程,使其接收。 在類的內部定義 Thread _readThread; bool _keepReading; 打開串口后啟動線程 _keepReading = true; _readThread = new Thread(ReadPort); _readThread.Start(); 線程函數 [csharp] view plaincopyprint?private void ReadPort() { while (_keepReading) { if (com.IsOpen) { byte[] readBuffer = new byte[com.ReadBufferSize + 1]; try { // If there are bytes available on the serial port, // Read returns up to "count" bytes, but will not block (wait) // for the remaining bytes. If there are no bytes available // on the serial port, Read will block until at least one byte // is available on the port, up until the ReadTimeout milliseconds // have elapsed, at which time a TimeoutException will be thrown. int count = com.Read(readBuffer, 0, com.ReadBufferSize); String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count); if (count != 0) //byteToHexStr(readBuffer); ThreadFunction(byteToHexStr(readBuffer,count)); } catch (TimeoutException) { } } else { TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50); Thread.Sleep(waitTime); } } } private void ReadPort() { while (_keepReading) { if (com.IsOpen) { byte[] readBuffer = new byte[com.ReadBufferSize + 1]; try { // If there are bytes available on the serial port, // Read returns up to "count" bytes, but will not block (wait) // for the remaining bytes. If there are no bytes available // on the serial port, Read will block until at least one byte // is available on the port, up until the ReadTimeout milliseconds // have elapsed, at which time a TimeoutException will be thrown. int count = com.Read(readBuffer, 0, com.ReadBufferSize); String SerialIn = System.Text.Encoding.ASCII.GetString(readBuffer, 0, count); if (count != 0) //byteToHexStr(readBuffer); ThreadFunction(byteToHexStr(readBuffer,count)); } catch (TimeoutException) { } } else { TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50); Thread.Sleep(waitTime); } } } 方法二:使用C#自帶的SerialPor控件。 1...在“工具箱”的“組件”中選擇SerialPor控件添加。 2...設置串口並打開 serialPort1.PortName = "COM1"; serialPort1.BaudRate = 9600; serialPort1.Open(); 3...寫入數據可以使用Write或者下面的函數 serialPort1.WriteLine(str); 4...添加數據接收的事件 private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 使用中的一些常見問題 C#中SerialPort類中DataReceived事件GUI實時處理方法(來自wanglei_wan@yahoo.com.cn 的看法) MSDN:從 SerialPort 對象接收數據時,將在輔助線程上引發 DataReceived 事件。由於此事件在輔助線程而非主線程上引發,因此嘗試修改主線程中的一些元素(如 UI 元素)時會引發線程異常。如果有必要修改主 Form 或 Control 中的元素,必須使用 Invoke 回發更改請求,這將在正確的線程上執行.進而要想將輔助線程中所讀到的數據顯示到主線程的Form控件上時,只有通過Invoke方法來實現 下面是代碼實例: [csharp] view plaincopyprint?private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { int SDateTemp = this.serialPort1.ReadByte(); //讀取串口中一個字節的數據 this.tB_ReceiveDate.Invoke( //在擁有此控件的基礎窗口句柄的線程上執行委托Invoke(Delegate) //即在textBox_ReceiveDate控件的父窗口form中執行委托. new MethodInvoker( /*表示一個委托,該委托可執行托管代碼中聲明為 void 且不接受任何參數的任何方法。 在對控件的 Invoke 方法進行調用時或需要一個簡單委托又不想自己定義時可以使用該委托。*/ delegate{ /*匿名方法,C#2.0的新功能,這是一種允許程序員將一段完整代碼區塊當成參數傳遞的程序代碼編寫技術,通過此種方法可 以直接使用委托來設計事件響應程序以下就是你要在主線程上實現的功能但是有一點要注意,這里不適宜處理過多的方法,因為C#消息機制是消息流水線響應機制,如果這里在主線程上處理語句的時間過長會導致主UI線程阻塞,停止響應或響應不順暢,這時你的主form界面會延遲或卡死 */ this.tB_ReceiveDate.AppendText(SDateTemp.ToString());//輸出到主窗口文本控件 this.tB_ReceiveDate.Text += " ";} ) ); } private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { int SDateTemp = this.serialPort1.ReadByte(); //讀取串口中一個字節的數據 this.tB_ReceiveDate.Invoke( //在擁有此控件的基礎窗口句柄的線程上執行委托Invoke(Delegate) //即在textBox_ReceiveDate控件的父窗口form中執行委托. new MethodInvoker( /*表示一個委托,該委托可執行托管代碼中聲明為 void 且不接受任何參數的任何方法。 在對控件的 Invoke 方法進行調用時或需要一個簡單委托又不想自己定義時可以使用該委托。*/ delegate{ /*匿名方法,C#2.0的新功能,這是一種允許程序員將一段完整代碼區塊當成參數傳遞的程序代碼編寫技術,通過此種方法可 以直接使用委托來設計事件響應程序以下就是你要在主線程上實現的功能但是有一點要注意,這里不適宜處理過多的方法,因為C#消息機制是消息流水線響應機制,如果這里在主線程上處理語句的時間過長會導致主UI線程阻塞,停止響應或響應不順暢,這時你的主form界面會延遲或卡死 */ this.tB_ReceiveDate.AppendText(SDateTemp.ToString());//輸出到主窗口文本控件 this.tB_ReceiveDate.Text += " ";} ) ); } 如何知道當前電腦有哪個串口 在窗體上添加一個comboBox控件。 然后使用comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames()); 或者 string[] portList = System.IO.Ports.SerialPort.GetPortNames(); for (int i = 0; i < portList.Length; ++i) { string name = portList[i]; comboBox1.Items.Add(name); } 具體請參考http://msdn.microsoft.com/zh-tw/library/system.io.ports.serialport.getportnames.aspx