取消订阅活动仍然会多次被解雇,如何阻止它? [英] Unsubscribing from an event still it's getting fired many times, how to stop it?

查看:94
本文介绍了取消订阅活动仍然会多次被解雇,如何阻止它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先我正在订阅一个事件,然后在该事件发生时将执行的方法我取消订阅它。但我仍然认为它被解雇了很多次。



我尝试过:



使用System; 
使用System.Collections.Generic;
使用System.IO;
使用System.IO.Ports;
使用System.Linq;
使用System.Text;
使用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();




}


}
}







使用System; 
使用System.Collections.Generic;
使用System.IO.Ports;
使用System.Linq;
使用System.Text;
使用System.Threading.Tasks;

namespace SerialPortHexCommunication
{
public class cEventHandler
{
public void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{// this In
//应该只打印一次数据接收消息,因为我取消订阅但是多次打印。
Console.WriteLine(在数据接收中);
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(缓冲区中的字节项)
{
Console.WriteLine(item);

}

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

解决方案

请看看你的代码!

为什么要这样写:

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

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

如果它是一个新端口,它就无法打开 - 这也是一样,因为你的应用程序会立即崩溃试图成熟你刚刚处置过的一个端口......



第二点要注意的是,多个DataReceived事件正是你应该期待的:串行数据被称为因为它以串行方式逐字节到达,而不是作为信息的托管包:每个字节都可能导致单独的DataReceived事件被触发。



I两天前告诉你这个!


 DataReceived 

事件应该在调用

 Open()方法

 SerialPort 

类。



根据您的结果事件被多次调用 - 在我的只有在来自另一个配对端口的任何响应的情况下才会调用case事件。



对于ex。配对端口是 - COM5< - > COM3所以当任何响应来自COM3端口时,将调用

 DataReceived 

事件。



无需取消订阅该事件。


Quote:

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



您已为事件添加了两个处理程序。因此,每次引发事件时,您的事件处理程序都会被调用两次。



引用:

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



该行将有没有效果。



当从事件中删除指向实例方法的委托时,委托指向的对象引用将作为其标识的一部分包含在内。由于您正在创建类的新实例,因此您创建的委托不等于该事件的任何已注册处理程序,因此删除它不会执行任何操作。



之前的 port.DataReceived - =新的SerialDataReceivedEventHandler(DataReceivedHandler); 行应该已经删除了处理程序,所以你可以删除这一行。


First I am subscribing to an event and then in the method which will be executed when that event occurs i am unsubscribing it.But still I think it is getting fired many times.

What I have tried:

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();
        }
    }
}

解决方案

Please, look at your code!
Why would you write this:

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

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

If it's a new port, it can't be open - which is just as well, as your app would then crash immediately as you tried to oipen a port you had just Disposed...

The second thing to note is that multiple DataReceived events are exactly what you should expect: Serial data is called that because it arrives in a serial fashion, byte by byte instead of as a "managed packet" of information: each byte can cause a separate DataReceived event to fire.

I told you this two days ago!


DataReceived

event should be subscribed before calling

Open()

method of

SerialPort

class.

As per your result event is called many times- In my case event will be called only in case of any response comes from another paired port.

For ex. Paired ports are - "COM5" <-> "COM3" so when any response will come from "COM3" port then the

DataReceived

event will be called.

There is no need to unsubscribe the event.


Quote:

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


You've added two handlers to the event. Therefore, every time the event is raised, your event handler will be called twice.

Quote:

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


That line will have no effect.

When a delegate pointing to an instance method is removed from an event, the object reference to which the delegate points is included as part of its identity. Since you're creating a new instance of your class, the delegate you create is not equal to any of the registered handlers for the event, so removing it doesn't do anything.

The previous port.DataReceived -= new SerialDataReceivedEventHandler(DataReceivedHandler); line should already remove the handler, so you can just delete this line.


这篇关于取消订阅活动仍然会多次被解雇,如何阻止它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆