0


1

特定の間隔でシリアルポートからデータを読み取りますか?

シリアルポートインターフェイスを備えた磁気カードリーダーがあります。

次のC#.netコードを使用して、コマンドをカードリーダーに送信しました。

System.IO.Ports.SerialPort myport = new System.IO.Ports.Serialport("COM1", 9600, Parity.Nonek, 8, StopBits.One);
myport.Open();
// initiates the card reader to read.
myport.write("command to initiate card reader");

// Once the card is swiped it shows the read data.
MessageBox.Show(myport.ReadExisting());
myport.Close();

上記のコードは、Messageboxの前に一時停止するときにうまく機能します。 しかし、私は一時停止したくありません。むしろ、カードがスワイプされるたびにメッセージボックスを開始したいです。

どうすればできますか?

これをユーザーログインシステムに実装しています。

1 Answer


3


カードスワイプで更新したいGUIがあると思います。 「textBox1」と呼ばれる単一のテキストボックスと「Start」(button1)というラベルの付いたボタンがあるフォームがあると仮定します。

using System;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;

namespace SerialPortExample {
    public partial class Form1 : Form {

        SerialPort myport;

        public Form1() {
            InitializeComponent();

            myport = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
            myport.DataReceived += new SerialDataReceivedEventHandler(myport_DataReceived);
            myport.ErrorReceived += new SerialErrorReceivedEventHandler(myport_ErrorReceived);
        }

        delegate void SerialDataReceivedDelegate(object sender, SerialDataReceivedEventArgs e);
        delegate void SerialErrorReceivedDelegate(object sender, SerialErrorReceivedEventArgs e);

        void myport_ErrorReceived(object sender, SerialErrorReceivedEventArgs e) {
            if (this.InvokeRequired) {
                this.Invoke(new SerialErrorReceivedDelegate(myport_ErrorReceived_Client), sender, e);
            } else {
                myport_ErrorReceived_Client(sender, e);
            }
        }

        void myport_ErrorReceived_Client(object sender, SerialErrorReceivedEventArgs e) {
            MessageBox.Show("Error recieved: " + e.EventType);
        }



        void myport_DataReceived(object sender, SerialDataReceivedEventArgs e) {
            if (this.InvokeRequired) {
                this.Invoke(new SerialDataReceivedDelegate(myport_DataRecieved_Client), sender, e);
            } else {
                myport_DataRecieved_Client(sender, e);
            }
        }

        void myport_DataRecieved_Client(object sender, SerialDataReceivedEventArgs e) {
            textBox1.Text = myport.ReadExisting();
        }

        private void button1_Click(object sender, EventArgs e) {
            try {
                if (myport.IsOpen) {
                    myport.Close();
                    button1.Text = "Start";
                } else {
                    myport.Open();
                    button1.Text = "Stop";
                }
            } catch (IOException ex) {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

このコードをテストするためのシリアルデバイスはありませんが、正しいはずです。

分解すると、重要な部分はメソッド `myport_DataRecieved`です。 このメソッドは、データがシリアルポートに到着するたびに呼び出されます。 カードがスワイプされたとき。

他の関心のある領域は、SerialPortを初期化する(しかしまだ開いていない) Form1`コンストラクターと、ポートを開閉する(そしてボタンのテキストを変更してそれを反映する) button1_Click`メソッドです。 何らかの理由でポートを開けない場合に備えて、例外も処理します。

編集:ハンスのコメントのおかげで、答えを更新しました。 別のスレッドで実行されるため、データイベントからUIコントロールに直接アクセスすることはできません。 イベントメソッドを半分に分割して、それらに対して「呼び出し」を呼び出し、適切なコンテキストで実行できるようにしました。