0

誰かが固定電話に電話をかけたときに、SerialPort を使用して発信者 ID を取得しています。PuTTy ソフトウェアを使用してテストしましたが、正常に動作します。

ただし、私の C# コードは InvalidOperation 例外をスローし、「クロススレッド操作が無効です: コントロールlblCallerIDTitleが作成されたスレッド以外のスレッドからアクセスされました。このエラーは、次のことをしようとすると発生します。lblCallerIDTitle.Text = ReadData;

どうすればこれを修正できますか? 以下は私のコードです:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace CallerID
{
    public partial class CallerID : Form
    {
        public CallerID()
        {
            InitializeComponent();
            port.Open();
            WatchModem();
            SetModem();
        }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        WatchModem();
    }

    private SerialPort port = new SerialPort("COM3");
    string CallName;
    string CallNumber;
    string ReadData;

    private void SetModem()
    {
        port.WriteLine("AT+VCID=1\n");
        port.RtsEnable = true;
    }

    private void WatchModem()
    {
        port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
    }

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        ReadData = port.ReadExisting();
        //Add code to split up/decode the incoming data
        lblCallerIDTitle.Text = ReadData;
        Console.WriteLine(ReadData);
    }

    private void CallerID_Load(object sender, EventArgs e)
    {

    }
  }
}

着信データを表示するラベルが必要です。ありがとう

4

2 に答える 2

3

ユーザー コントロール (ラベルなど) は UI スレッドで更新する必要があり、シリアル データは別のスレッドで受信されます。

2 つのオプションは、Invoke() を使用してコントロールの更新をメイン UI スレッドにプッシュするか、シリアル スレッドに変数を更新させ、タイマー コントロールを使用してその変数をチェックしてラベルを更新することです。

最初の (より良い) オプションのコードは、次のようになります。

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    ReadData = port.ReadExisting();
    //Add code to split up/decode the incoming data
    if (lblCallerIDTitle.InvokeRequired)
        lblCallerIDTitle.Invoke(() => lblCallerIDTitle.Text = ReadData);
    else
        lblCallerIDTitle.Text = ReadData;
    Console.WriteLine(ReadData);
}

その後、ラベルは常にメイン UI スレッドで更新されます。

于 2012-06-05T14:41:00.870 に答える
2

Invoke別のスレッドから UI を更新するときに使用する必要があります。

交換...

lblCallerIDTitle.Text = ReadData

... と ...

lblCallerIDTitle.Invoke(new SetCallerIdText(() => lblCallerIDTitle.Text = ReadData));

...これをクラスのどこかで宣言した後...

public delegate void SetCallerIdText();

私はこの質問への答えが好きですが。

于 2012-06-05T14:47:26.190 に答える