1

シリアルポートを介してデータを受信するためのハンドラーでは、データを受信すると、それを文字列に格納し、.contains検索を実行して、データに対して何かを行う必要があるかどうかを判断します。アプリケーションがアイドル状態にあり、(モデムと呼びます)が「接続済み」のようなものを送信すると、正常に動作します。

問題は、マシンをポーリングするときです。戻り結果を期待するコマンドを開始すると、機能せず、理由がわかりません。ここで、メッセージボックスを使用して関数を開始すると、機能します。不要なメッセージボックスは必要ありません。

これが私のコードのサンプルです。

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    if (this.InvokeRequired)
    {
        RefreshTextBox d = new RefreshTextBox(RefreshTextBoxResults);
        Invoke(d);
    }
    else
    {
        RefreshTextBoxResults();
    }
}

private void RefreshTextBoxResults()
{
    //MessageBox.Show("refresh text is occurring");
    indata1 = serialPort1.ReadExisting();
    rx.AppendText(indata1);

    string dataCheck = indata1.ToUpper();

    //MessageBox.Show(dataCheck);
    if (indata1.ToUpper().Contains("CONNECT"))//dataCheck.Contains("CONNECT"))
    {
        // MessageBox.Show("connect");
        cState.Text = "Connected";
        if(connected==false)
            connectLink();
    }
    if (dataCheck.Contains("CONNECTED"))
    {
        // MessageBox.Show("Active Call in Session");
        cState.Text = "Connected";
        if (connected==false)
            connectLink();
    }
    if (dataCheck.Contains("NO"))
    {
        cState.Text = "Disconnected";
        disconnect();
    }
    if (dataCheck.Contains("CAMPOS"))
    {
        campos = indata1;
        camDat = true;
    }
}

private void cState_Click(object sender, EventArgs e)
{
    writeDevice("callstatus");
}

public void writeDevice(string cmd)
{
    try
    {
        {
            serialPort1.Write(cmd + "\r\n");
        }
    }
    catch
    { noconnect(); }
}

cstate()を実行すると、呼び出しステータスとタイプ(存在する場合)が返されます。プロンプトボックスに表示されているように、モデムは応答します。「接続済み」という単語がそこにある場合は、ラベルのテキストを「接続済み」に変更する必要があります。コードが置かれている間、そのラベルには何も起こりません。しかし、RefreshTextBoxResults()の最初の行のコメントを削除して、そのMessageBoxをアクティブにすると、モデムのステータスが検出されます。

何が起こっているのかわかりません。なぜこれが起こっているのか誰かが私に説明できますか?

4

3 に答える 3

3

しかし、RefreshTextBoxResults()の最初の行のコメントを削除すると

それがキーフレーズです。問題は、ReadExisting()を使用することです。シリアルポートは非​​常に低速であり、DataReceivedイベントハンドラーは通常1文字または2文字しか取得しません。メッセージボックスを表示することで、速度を落とすことができます。これにより、シリアルポートドライバはより多くの文字を読み取ることができます。ReadExistingは、「C」または「Co」だけでなく、「Connected」文字列全体を読み取るのに十分です。

デバッガーを使用する場合も診断が難しく、コードを1ステップ実行すると、ポートが十分な文字を取得できるように、コードの速度が低下します。

あなたがする必要があるのは、応答文字列全体を取得した後にのみ応答を処理することです。これはモデムではいつでも簡単です。ReadExisting()の代わりにReadLine()を使用するだけです。NewLineプロパティの値を微調整する必要がある場合があります。

于 2012-08-29T23:50:34.670 に答える
1

MessageBox()モーダルダイアログメッセージループを開始します。これにより、キューに入れられたウィンドウメッセージを処理する機会が与えられます。RefreshTextboxResults()関数でテキストボックスコントロールに対して行っている操作の一部は、コントロールウィンドウのハンドルにメッセージを送信すると考えられます。この場合、ウィンドウハンドルは、実行フローがメッセージループに入る、またはメッセージループに戻るまで、そのようなメッセージを受信しません。これは、モーダルダイアログ(MessageBoxなど)を開いた場合に関数で発生します。

これが解決策であるというわけではありませんが、この理論を確認する必要があります。MessageBox()への呼び出しに置き換えてみてくださいApplication.DoEvents()。(アプリがWinFormsアプリであると仮定します)これにより、呼び出しと同じ程度にブロックが解消された場合、MessageBox()処理する必要のある保留中のメッセージがメッセージキューに積み上げられていることは明らかです。

于 2012-08-29T23:27:55.333 に答える
0

データが完全に受信されるまでアプリケーションをブロックするか、バックグラウンドトレッドを使用して作業を行うことをお勧めします。

于 2012-08-30T17:58:45.727 に答える