4

C#アプリケーションを介して指紋スキャナーからデータを取得しようとしていますが、指紋が送信される前にコード全体が実行されます。

System.Threading.Thread.Sleep(1000)次のステップが実行される前にデータを取得できるように、遅延関数とを使用してみましたが、すべて無駄に思えます。

他のオプションを教えてください。

" " を使用SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)してデータを取得しています。

4

5 に答える 5

3

残念ながら、C# でシリアル ポートのデータを待つのはトリッキーpoll()です。

SerialPort.DataReceived着信データに対して呼び出される関数を受け取るものがあります。したがって、任意のイベントをトリガーする関数をそこに割り当てます。別の関数 (実際に待機する関数) は、このイベントを待機する必要があります。

以下は簡単な例で、コメントが付けられていますが、要するに: はTestFuncシリアル ポートを初期化して開きます(特に を割り当てますDataReceived)。はProxy()、データが到着するたびに呼び出される関数で、イベントをトリガーします。WaitForAData()実際、データが表示されたときにトリガーされるイベントを待ちますProxy()lock(){}の関数を囲むMonitors がないと、正しく動作しないことに注意してください。

WaitForAData()これは単なる例です。おそらく、タイムアウトの場合に例外をトリガーするように関数を作り直す必要があるでしょう。また、待機を開始する前にトリガーされた場合に備えてブール変数を追加するにはProxy()、シリアルポートに既にデータがあります。しかし、私はそれをテストしました(私は今そのような機能が必要です☺)、そしてそれは動作します.

namespace MyNamespace
{

class MySerial
{
    ///A condition variable that signals when serial has a data
    private System.Object SerialIncoming;

    public MySerial()
    {
        SerialIncoming = new Object();
    }

    /**
     * A proxy function that will be called every time a data arrived
     */
    private void Proxy(Object unused1, SerialDataReceivedEventArgs unused2)
    {
        Console.WriteLine("Data arrived!");
        lock (SerialIncoming)
        {
            Monitor.Pulse(SerialIncoming);
        }
    }

    /**
     * Waits for a data for the time interval Timeout
     * \param Timeout a timeout in milliseconds to wait for a data
     * \returns true in if a data did arrived, and false else
     */
    public bool WaitForAData(int Timeout)
    {
        lock (SerialIncoming)//waits N seconds for a condition variable
        {
            if (!Monitor.Wait(SerialIncoming, Timeout))
                {//if timeout
                    Console.WriteLine("Time out");
                    return false;
                }
            return true;
        }
    }

    /* Just a test function: opens a serial with speed, and waits
     * for a data for the «Timeout» milliseconds.
     */
    public void TestFunc(string serial, int speed, int Timeout)
    {
        SerialPort ser = new SerialPort(serial);
        ser.BaudRate = speed;
        ser.DataReceived += Proxy;
        ser.Open();
        if (WaitForAData(Timeout))
            Console.WriteLine("Okay in TestFunc");
        else
            Console.WriteLine("Time out in TestFunc");
    }
}

}

更新:問題は私の 1 日の ½ を無駄にしたので、誰かの時間を節約できることを願っています: 上記のコードはモノラルでは機能しません (ただし、MS 実装では機能します)

于 2014-10-17T10:10:59.103 に答える
3

このコードは私にとって完璧に機能します:

port = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
port.Open();
port.DiscardOutBuffer();
port.DiscardInBuffer();
port.DataReceived += OnScan;

void OnScan(object sender, SerialDataReceivedEventArgs args)
{
    SerialPort port = sender as SerialPort;

    string line = port.ReadExisting();
// etc
}
于 2013-07-25T05:56:24.737 に答える
1

これがコンソール アプリケーションの場合Console.ReadLine()は、COM ポート コンポーネントの適切な関数を呼び出して、非同期でリッスンを開始した後、などを使用できます。これが WinForms アプリケーションの場合。もちろん、メッセージ ループは現在のフォームを表示し続けます。その場合、Form_Loadイベント内またはボタンクリックの背後で非同期リスニング関数を呼び出すことができます。

ここで重要な点は、リスナー関数の非同期バージョンを呼び出す必要があるということです。その場合、遅延やタイマーを使用する必要はありません。

于 2013-07-25T05:54:17.450 に答える
0

グローバル マーカー (bool) を作成して、何かを受信したかどうかをマークし、while(!marker) {} ループを作成して、SerialPort_datareceived サブルーチンでマーカーを変更してみませんか?

thread.sleep により、SerialPort のデータ送信を見逃す可能性がありますか?

于 2013-07-25T05:56:02.813 に答える