www.pudn.com > GPSIOSerialPort.rar > GPSSoftware.cs


using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using System.IO.Ports; 
using System.Threading; 
 
namespace GPSIOSerialPort 
{ 
    public partial class GPSSoftware : Form 
    { 
        private SerialPort myPort; 
        private EventHandler updateDataHandle; 
        private string currentData; 
 
        public GPSSoftware() 
        { 
            InitializeComponent(); 
 
            this.selectedPort.SelectedIndex = 5; 
            this.selectedRate.SelectedIndex = 0; 
 
            myPort = new SerialPort("COM6", 4800); 
            myPort.Parity = Parity.None; 
            myPort.StopBits = StopBits.One; 
            myPort.DataBits = 8; 
            myPort.ReadTimeout = 1000; 
 
            #region 线程中调用控件的两种方法 
            //以下为线程调用控件的两种办法: 
            //法一:(可用于PC和PDA两种情况,可见于本程序) 
            /*虽然多线程处理最适于运行过程和类方法,它也可以用于窗体和控件。使用时,请注意以下几点: 
 
            (1)只要有可能,便仅在用来创建它的线程上执行控件的各种方法。若须从另一线程调用控件的方法,则必须使用 Invoke 来调用该方法。 
 
            (2)不要使用 SyncLock 语句锁定操作控件或窗体的线程。由于控件和窗体的方法有时回调到调用过程,因此可能会因无意中创建了死锁而终止运行(死锁是指两个线程都等待对方释放锁定,从而导致应用程序暂停的情况)。*/ 
 
            //法二:(只可用于PC,2003版本的vs不需要) 
            //Control.CheckForIllegalCrossThreadCalls = false; 
            #endregion 
 
            updateDataHandle = new EventHandler(updateGpsData); 
        } 
 
        private void open_Click(object sender, EventArgs e) 
        { 
            gpsInfo.Text = "正在打开串口!\r\n"; 
            myPort.Open(); 
 
            if (myPort.IsOpen) 
            { 
                gpsInfo.Text += "串口已打开,正在等待GPS数据!\r\n"; 
                myPort.DataReceived += new SerialDataReceivedEventHandler(myPort_DataReceived); 
            } 
            else 
            { 
                gpsInfo.Text += "串口打开失败!\r\n"; 
            } 
        } 
 
        public void myPort_DataReceived(object sender, SerialDataReceivedEventArgs e) 
        { 
            //说明:可能读取到的数据长度不定,若直接读取512字节,则可能造成各次触发都等待读取512字节数据。,所以安全的措施是读取myPort.BytesToRead这么长。 
            int len = myPort.BytesToRead; 
            Byte[] buffer = new Byte[len]; 
            myPort.Read(buffer, 0, len); 
            if (len == 0) 
            { 
                return; 
            } 
            else 
            { 
                currentData = Encoding.ASCII.GetString(buffer, 0, buffer.Length); 
                //这里使用gpsInfo.Text += Encoding.ASCII.GetString(buffer, 0, buffer.Length);是错误的.因为CE不允许子线程调用控件 
                Invoke(updateDataHandle); 
            } 
        } 
 
        private void updateGpsData(object sender, EventArgs e) 
        { 
            gpsInfo.Text += currentData; 
            if (gpsInfo.Text.Length > 5000) 
            { 
                gpsInfo.Text = gpsInfo.Text.Substring(5000, gpsInfo.Text.Length - 5000); 
                System.GC.Collect(); 
            } 
        } 
 
        private void close_Click(object sender, EventArgs e) 
        { 
            if (myPort.IsOpen) 
            { 
                myPort.DataReceived -= new SerialDataReceivedEventHandler(myPort_DataReceived); 
                myPort.Close(); 
            } 
        } 
 
        private void exit_Click(object sender, EventArgs e) 
        { 
            if (myPort.IsOpen) 
            { 
                myPort.DataReceived -= new SerialDataReceivedEventHandler(myPort_DataReceived); 
                myPort.Close(); 
            } 
            Close(); 
        } 
 
    } 
}