saat menerima data, peristiwa [serialport_datareceived] terjadi lebih dari sekali (menggunakan port serial virtual)

Saya mencoba mengirim dan menerima data melalui komunikasi serial menggunakan program port serial virtual. Tapi ini masalahnya... Misalkan A mengirim data dan B menerima data.

Ketika A mengirim data ke B. B menerima data dua kali (peristiwa serialport_datareceived terjadi dua kali!).

Setiap kali B menutup serialport dan membuka kembali, peristiwa serialport_datareceived terjadi meningkat.

Saya tidak tahu mengapa ini terjadi.

A(transmit)
BaudRate = 9600
Parity = None
DataBits = 8
StopBits = 1

    public transmit()
    {
        InitializeComponent();
        foreach (String s in System.IO.Ports.SerialPort.GetPortNames())
        {
            cBoxPort.Items.Add(s);          
        }
    }
    private void CBoxBaudRate_SelectedIndexChanged(object sender, EventArgs e)
    {
        serialPort1.BaudRate = Convert.ToInt32(cBoxBaudRate.Text);                          
    }
    private void CBoxStopBits_SelectedIndexChanged(object sender, EventArgs e)
    {
        serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cBoxStopBit.Text);   
    }
    private void CBoxDataBits_SelectedIndexChanged(object sender, EventArgs e)
    {
        serialPort1.DataBits = Convert.ToInt32(cBoxDataBits.Text);                          
    }
    private void CBoxParityBits_SelectedIndexChanged(object sender, EventArgs e)
    {
        serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), cBoxParity.Text);           
    }

    private void btnConnect_Click(object sender, EventArgs e)
    {
        try
        {
            serialPort1.PortName = cBoxPort.Text;
            serialPort1.BaudRate = Convert.ToInt32(cBoxBaudRate.Text);
            serialPort1.DataBits = Convert.ToInt32(cBoxDataBits.Text);
            serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cBoxStopBit.Text);
            serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), cBoxParity.Text);
            serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
            serialPort1.Open();

            txtReceive.AppendText("Connected\n");   
            btnConnect.Enabled = false;             
            btnClose.Enabled = true;
            btnSend.Enabled = true;
        }

        catch (Exception ex)
        {
            return;
        }
    }
    private void btnClose_Click(object sender, EventArgs e)
    {
        if (serialPort1.IsOpen)
        {
            serialPort1.Close();                        
            btnClose.Enabled = false;
            btnConnect.Enabled = true;
            btnSend.Enabled = false;
            txtReceive.AppendText("Disconnected\n");  
        }
    }

    private void btnSend_Click(object sender, EventArgs e)
    {
        byte[] bytesend = { 0x00 };
        Debug.WriteLine("111");
        serialPort1.Write(bytesend, 0, bytesend.Length);
    }

    private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        Debug.WriteLine("444");
    }

}

B (menerima)

    byte[] bytesend;

    //Initial Conditions(SerialPort)
    private void receive_Load(object sender, EventArgs e)
    {
        cBoxBaudRate.SelectedIndex = 0;     //BaudRate = 9600
        cBoxParity.SelectedIndex = 0;       //Parity = None
        cBoxDataBits.SelectedIndex = 0;     //DataBits = 8
        cBoxStopBit.SelectedIndex = 0;      //StopBits = 1
        cBoxPort.SelectedIndex = 1;         

        btnConnect.Enabled = true;
        btnClose.Enabled = false;
    }

    //Show usable CommPort
    public receive()
    {
        InitializeComponent();
        foreach (String s in System.IO.Ports.SerialPort.GetPortNames())
        {
            cBoxPort.Items.Add(s);
        }
    }

    //Connection
    private void btnConnect_Click(object sender, EventArgs e)
    {
        serialPort1.PortName = cBoxPort.Text;
        serialPort1.BaudRate = Convert.ToInt32(cBoxBaudRate.Text);
        serialPort1.DataBits = Convert.ToInt32(cBoxDataBits.Text);
        serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cBoxStopBit.Text);
        serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), cBoxParity.Text);
        serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
        serialPort1.Open();

        btnConnect.Enabled = false;
        btnClose.Enabled = true;
    }
    private void btnClose_Click(object sender, EventArgs e)
    {
        if (serialPort1.IsOpen)
        {
            serialPort1.Close();
            btnClose.Enabled = false;
            btnConnect.Enabled = true;
        }
    }

    private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        Debug.WriteLine("222");
    }

ketika saya men-debug keluaran kode ini mewakili 111 222 222. Dan ketika saya menekan tombol tutup dan sambungkan, keluarannya mewakili 111 222 222 222.


person kmg    schedule 14.02.2019    source sumber
comment
Pada tombol koneksi, Anda menghubungkan acara DataReceived SETIAP kali. Anda hanya ingin melakukan ini SEKALI, seperti pada acara Load() di Formulir...   -  person Idle_Mind    schedule 14.02.2019
comment
terima kasih atas komentar Anda. tetapi jika Anda tidak keberatan, bisakah Anda menulis komentar dengan lebih tepat?   -  person kmg    schedule 14.02.2019
comment
Saya mendengar bahwa hal itu terjadi karena multi-thread. Apakah saya benar? jika itu terjadi karena masalah multi-thread, bagaimana cara memperbaikinya?   -  person kmg    schedule 14.02.2019


Jawaban (1)


Setiap kali B menutup serialport dan membuka kembali, peristiwa serialport_datareceived terjadi meningkat.

Benar, karena seperti yang saya katakan, Anda hanya boleh menghubungkan acara DataReceived SEKALI. Setiap kali Anda mengeklik tombol, pengendali lain akan ditambahkan, menghasilkan beberapa pengaktifan untuk satu penerimaan. Ini tidak ada hubungannya dengan multi-threading. Pindahkan garis yang menghubungkan handler dari event klik tombol ke event Load:

private void transmit_Load(object sender, EventArgs e)
{
    serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived); // now it only gets called once
    // ... other existing code ...
}


private void btnConnect_Click(object sender, EventArgs e)
{
    try
    {
        serialPort1.PortName = cBoxPort.Text;
        serialPort1.BaudRate = Convert.ToInt32(cBoxBaudRate.Text);
        serialPort1.DataBits = Convert.ToInt32(cBoxDataBits.Text);
        serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cBoxStopBit.Text);
        serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), cBoxParity.Text);
        // serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);  // remove this line
        serialPort1.Open();

        txtReceive.AppendText("Connected\n");   
        btnConnect.Enabled = false;             
        btnClose.Enabled = true;
        btnSend.Enabled = true;
    }

    catch (Exception ex)
    {
        return;
    }
}

Anda juga perlu melakukan hal yang sama di formulir penerimaan Anda.

person Idle_Mind    schedule 14.02.2019
comment
Idle_Mind benar. Anda dapat menulis program Anda untuk dibaca hanya ketika tombol diklik atau dibaca setiap kali data muncul tetapi tidak keduanya. Pilih salah satu yang paling sesuai dengan aplikasi Anda. - person skinnedKnuckles; 14.02.2019
comment
Dia juga bisa melakukan -= dalam fungsi close-nya. - person Baddack; 14.02.2019