Nishikant Tayade Ответов: 3

Отписавшись от события, все равно его увольняют много раз, как это остановить?


Сначала я подписываюсь на событие, а затем в методе, который будет выполнен, когда это событие произойдет, я отменяю его подписку.Но все же я думаю, что его увольняют много раз.

Что я уже пробовал:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SerialPortHexCommunication
{
    public class Program
    {
        private static bool unsubscribe=false;

        static void Main(string[] args)
        {

            SerialPort port = new SerialPort();
            port.PortName = "COM5";
            port.Parity = Parity.None;
            port.BaudRate = 9600;
            port.DataBits = 8;
            port.StopBits = StopBits.One;
          
            if (port.IsOpen)

            {
                port.Close();
                port.Dispose();
            }
             port.Open();

            byte[] bytesToSend = new byte[6] { 0xD0, 0xF2, 0xFF, 0x00, 0x06, 0xC7 };

            port.Write(bytesToSend, 0, bytesToSend.Length);

      
            port.DataReceived += new SerialDataReceivedEventHandler(new cEventHandler().DataReceivedHandler);

            port.DataReceived -= new SerialDataReceivedEventHandler(new cEventHandler().DataReceivedHandler);

            Console.ReadKey();
            port.Close();
            port.Dispose();

            
           

        }

      
    }
}



using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SerialPortHexCommunication
{
   public class cEventHandler
    {
        public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {//this In data receive message should be printed only once
         //as i am unsubscribing but it get printed many times.
            Console.WriteLine("In data receive");
            SerialPort port = (SerialPort)sender;
            port.DataReceived -= new SerialDataReceivedEventHandler(DataReceivedHandler);

            int bytes = port.BytesToRead;
            byte[] buffer = new byte[bytes];

            if (port.BytesToRead > 1)
            {
                port.Read(buffer, 0, bytes);
            }

            foreach (byte item in buffer)
            {
                Console.WriteLine(item);

            }

            port.DataReceived -= new SerialDataReceivedEventHandler(new cEventHandler().DataReceivedHandler);
            //Console.ReadKey();
        }
    }
}

3 Ответов

Рейтинг:
28

OriginalGriff

Пожалуйста, посмотрите на свой код!
Зачем ты это пишешь:

            SerialPort port = new SerialPort();
...          
            if (port.IsOpen)

            {
                port.Close();
                port.Dispose();
            }
             port.Open();
Если это новый порт, он не может быть открыт - что очень хорошо, так как ваше приложение сразу же рухнет, как только вы попытаетесь открыть порт, который вы только что удалили...

Во-вторых, следует отметить, что множественные события DataReceived-это именно то, что вы должны ожидать: последовательные данные называются так, потому что они поступают последовательным образом, байт за байтом, а не как "управляемый пакет" информации: каждый байт может вызвать срабатывание отдельного события DataReceived.

Я же говорил тебе об этом два дня назад!


Рейтинг:
2

Chander Parkash Mourya

DataReceived
событие должно быть подписано перед вызовом
Open()
способ получения
SerialPort
класс.

В соответствии с вашим результатом событие вызывается много раз - в моем случае событие будет вызываться только в том случае, если какой-либо ответ придет из другого парного порта.

Например. Парные порты - "COM5" <-> "COM3", поэтому, когда какой-либо ответ придет из порта "COM3", то
DataReceived
событие будет названо.

Отписываться от мероприятия нет необходимости.


Nishikant Tayade

@ChanderParkashMourya как вы сказали, "когда какой-либо ответ придет из порта "COM3", то событие будет вызвано."

Но я хочу, чтобы он просто перестал спрашивать,когда придет первый ответ, в этом случае "In data receive" будет там только один раз, затем снова попросит данные и так далее.
возможно ли это?
Вот почему я пытался отказаться от подписки.

Chander Parkash Mourya

Событие DataReceived будет вызвано для отдельного потока, и вы не можете отменить подписку на событие вне потока.
для получения дополнительной информации вы можете перейти по этой ссылке -
https://msdn.microsoft.com/fi-fi/library/system.io.ports.serialport.datareceived(v=против 110).aspx

Рейтинг:
2

Richard Deeming

Цитата:
port.DataReceived += new SerialDataReceivedEventHandler(new cEventHandler().DataReceivedHandler);
port.DataReceived -= new SerialDataReceivedEventHandler(new cEventHandler().DataReceivedHandler);

Вы добавили два обработчика к событию. Поэтому каждый раз, когда событие вызывается, ваш обработчик событий будет вызываться дважды.

Цитата:
port.DataReceived -= new SerialDataReceivedEventHandler(new cEventHandler().DataReceivedHandler);

Эта линия не будет иметь никакого эффекта.

Когда делегат, указывающий на метод экземпляра, удаляется из события, ссылка на объект, на который указывает делегат, включается как часть его идентификатора. Поскольку вы создаете новый экземпляр своего класса, созданный вами делегат не равен ни одному из зарегистрированных обработчиков события, поэтому его удаление ничего не делает.

Предыдущее port.DataReceived -= new SerialDataReceivedEventHandler(DataReceivedHandler); строка уже должна удалить обработчик, поэтому вы можете просто удалить эту строку.