代表和活动混乱 [英] Delegates and Events confusion

查看:65
本文介绍了代表和活动混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个课程(让我们称之为ClassA)我写的有事件。

在另一个课程中(让我们称之为ClassB)我创建了一个集合ClassA

对象。在第三个类(ClassC)中,我创建了对在ClassB中创建的一些

ClassA对象的引用。在ClassC中,我使用foreach循环挂钩到ClassA事件

,以便挂钩每个对象。代码类似于

这个:

class ClassC {

void SomeMethod()

{

foreach(ClassACollection中的ClassA项目)

{

item.MyEvent + = new EventHandler(item_MyEvent);

} < br $>
}

}


ClassC类型的对象不断创建和删除,但
$ b $的对象b它引用的ClassA保留在内存中。因此,每次我加载一个新的ClassC实例时,该事件都会再次被钩住。我所看到的是

我发起了一次事件,但我最终在代码中引发它

每次响应它(item_MyEvent方法)它被添加,当我只是
想让它被抓到一次。


我怎么能确定我只为每个事件添加一次处理程序

项目?由于代码是在ClassC中,因此不允许检查

ClassA.MyEvent,看看是否有东西已经连接到它。


我希望这是有道理的。创建一个repro案例在这里没有意义

因为它是我的应用程序逻辑导致问题。


谢谢。

I have a class (let''s call it ClassA) that I''ve written which has events.
In another class (let''s call it ClassB) I create a collection of ClassA
objects. In a third class (ClassC) I create a reference to some of the
ClassA objects created in ClassB. In ClassC I hook into the ClassA events
with a foreach loop so that I hook each object. The code is something like
this:
class ClassC {
void SomeMethod()
{
foreach (ClassA item in ClassACollection)
{
item.MyEvent += new EventHandler(item_MyEvent);
}
}
}

Objects of type ClassC keep getting created and deleted, but the objects of
ClassA that it references stay in memory. Therefore, every time I load a
new instance of ClassC the event gets hooked again. What I''m seeing is that
I fire the event once but I end up getting it raised in the code that
responds to it (item_MyEvent method) for every time it was added when I only
want it to get caught once.

How can I be sure that I only add the handler to the event once for each
item? Since the code is in ClassC it''s not allowed to inspect the
ClassA.MyEvent to see if something''s already hooked to it.

I hope this makes sense. Creating a repro case wouldn''t make sense here
because it''s my application logic that''s causing the problem.

Thanks.

推荐答案

当您从内存中删除C类

的实例时,是否取消订阅该事件?


如果您订阅了一个活动并且没有取消订阅,则订阅者将在内存中保留
,直到收集到活动发布者(A类)。

这就是原因:

代表有一个名为Target的成员。 Target是对

订户(C类)的引用。当您添加事件时,发布者持有对委托的

引用,该委托又持有对订阅者的引用,

因此C保留在内存中。图表如下所示:


A ---> EventDelegate ----> C


所以,你得到多次事件火灾的原因是你在内存中的C实例多于
你认为你这样做了。


你可能想要做的是跟踪所有事件

订阅C和C实现IDispose 。当你准备好杀死C时,请调用它的Dispose方法。在Dispose内部,取消订阅您订阅的所有活动的



Rhy Mednick < rh*@rhy.com>写在消息

新闻:uV ************* @ TK2MSFTNGP09.phx.gbl ...
Are you unsubscribing the event when you remove the instances of Class C
from memory?

If you subscribe to an event and do not unsubscribe, the subscriber will be
held in memory until the event publisher (class A) is collected.

Here''s why:
A delegate has a member called Target. Target is a reference to the
subscriber (Class C). When you add the event, the publisher holds a
reference to the delegate which in turn holds a reference to the subscriber,
so C is held in memory. The graph looks like this:

A ---> EventDelegate ---->C

So, the reason that you are getting multiple event fires is that you have
more instances of C in memory than you think that you do.

What you probably want to do is to keep track of all of the event
subscriptions that C makes and have C implement IDispose. When you are
ready to kill C, call its Dispose method. Inside the Dispose, unsubscribe
from all of the events that you are subscribed to.

"Rhy Mednick" <rh*@rhy.com> wrote in message
news:uV*************@TK2MSFTNGP09.phx.gbl...
我有一个班级(让我称之为ClassA,我写的是有事件的。
在另一个类中(让我们称之为ClassB)我创建了一个ClassA
对象的集合。在第三个类(ClassC)中,我创建了对ClassB中创建的一些ClassA对象的引用。在ClassC中,我使用foreach循环挂钩到ClassA事件中,以便挂钩每个对象。代码是这样的

类ClassC {
void SomeMethod()
{/ /> foreach(ClassACollection中的ClassA项目)
{
item.MyEvent + = new EventHandler(item_MyEvent);
}
}


,我一次点击该事件,但我最终在每次添加时都会在代码中提出它(item_MyEvent方法)$ I
只希望它被抓到一次。

我怎么能确定我只为每个
项目添加一次处理程序?由于代码是在ClassC中,因此不允许检查ClassA.MyEvent,看看是否有东西已经连接到它。

我希望这是有道理的。创建一个repro案例在这里没有意义
因为它是我的应用程序逻辑导致问题。

谢谢。
I have a class (let''s call it ClassA) that I''ve written which has events.
In another class (let''s call it ClassB) I create a collection of ClassA
objects. In a third class (ClassC) I create a reference to some of the
ClassA objects created in ClassB. In ClassC I hook into the ClassA events
with a foreach loop so that I hook each object. The code is something like this:
class ClassC {
void SomeMethod()
{
foreach (ClassA item in ClassACollection)
{
item.MyEvent += new EventHandler(item_MyEvent);
}
}
}

Objects of type ClassC keep getting created and deleted, but the objects of ClassA that it references stay in memory. Therefore, every time I load a
new instance of ClassC the event gets hooked again. What I''m seeing is that I fire the event once but I end up getting it raised in the code that
responds to it (item_MyEvent method) for every time it was added when I only want it to get caught once.

How can I be sure that I only add the handler to the event once for each
item? Since the code is in ClassC it''s not allowed to inspect the
ClassA.MyEvent to see if something''s already hooked to it.

I hope this makes sense. Creating a repro case wouldn''t make sense here
because it''s my application logic that''s causing the problem.

Thanks.



谢谢。我想我需要以某种方式取消订阅但是因为我没有存储内部引用给订阅者。我添加了代码

,如下所示,它解决了问题,但我真的不明白

为什么:


item.MyEvent - = new EventHandler(item_MyEvent);


这对我来说真的很奇怪。如果+ =赋值添加了一个引用到
a的新事件处理程序,那么处理程序似乎与

不同的对象是在 - =赋值中使用new运算符创建的对象。我可以看到

这样的工作:

EventHandler eh = new EventHandler(item_MyEvent);

item.MyEvent + = eh;

....然后......

item.MyEvent - = eh;

我可以看到它正在工作,因为它是一样的对象,但是当我使用新的

关键字两次时,我没有两个独特的引用?


- Rhy

" J.Marsch" < JE **** @ ctcdeveloper.com>在留言中写道

新闻:%2 *************** @ TK2MSFTNGP12.phx.gbl ...
Thanks. I figured that I needed to unsubscribe in some way but since I
wasn''t storing an internal reference to the subscriber. I added the code
like the following and it solved the problem but I don''t really understand
why:

item.MyEvent -= new EventHandler(item_MyEvent);

This just seems really odd to me. If the += assignment adds a refernece to
a new event handler it seems that handler would be a different object than
the one created with the new operator in the -= assignment. I could see
something like this working:
EventHandler eh = new EventHandler (item_MyEvent);
item.MyEvent += eh;
....then later...
item.MyEvent -= eh;
I can see that working because it''s the same object, but when I use the new
keyword twice don''t I have two unique references?

- Rhy
"J.Marsch" <je****@ctcdeveloper.com> wrote in message
news:%2***************@TK2MSFTNGP12.phx.gbl...
你取消订阅了吗?从内存中删除C类实例的事件?

如果您订阅了一个活动并且没有取消订阅,订阅者将被保留在记忆直到事件发布者(A类)被收集。

这就是原因:
一个代表有一个名为Target的成员。 Target是对
订户(C类)的引用。当您添加事件时,发布者持有对委托的引用,该委托又持有对
订阅者的引用,因此C保存在内存中。图表看起来像这样:

A ---> EventDelegate ----> C

所以,你得到多个事件火灾的原因是你在内存中有比你想象的更多的C实例。 />
你可能想要做的是跟踪C所做的所有事件订阅,并使C实现IDispose。当你准备杀死C时,调用它的Dispose方法。在Dispose内部,取消订阅您订阅的所有活动。

Rhy Mednick < rh*@rhy.com>在消息中写道
新闻:uV ************* @ TK2MSFTNGP09.phx.gbl ...
Are you unsubscribing the event when you remove the instances of Class C
from memory?

If you subscribe to an event and do not unsubscribe, the subscriber will
be
held in memory until the event publisher (class A) is collected.

Here''s why:
A delegate has a member called Target. Target is a reference to the
subscriber (Class C). When you add the event, the publisher holds a
reference to the delegate which in turn holds a reference to the
subscriber,
so C is held in memory. The graph looks like this:

A ---> EventDelegate ---->C

So, the reason that you are getting multiple event fires is that you have
more instances of C in memory than you think that you do.

What you probably want to do is to keep track of all of the event
subscriptions that C makes and have C implement IDispose. When you are
ready to kill C, call its Dispose method. Inside the Dispose, unsubscribe
from all of the events that you are subscribed to.

"Rhy Mednick" <rh*@rhy.com> wrote in message
news:uV*************@TK2MSFTNGP09.phx.gbl...
我有一个班级(让'来电'它是ClassA)我写的有事件。
在另一个类中(我们称之为ClassB)我创建了一个ClassA
对象的集合。在第三个类(ClassC)中,我创建了对ClassB中创建的一些ClassA对象的引用。在ClassC中,我使用foreach循环挂钩到ClassA
事件,以便挂钩每个对象。代码是
I have a class (let''s call it ClassA) that I''ve written which has events.
In another class (let''s call it ClassB) I create a collection of ClassA
objects. In a third class (ClassC) I create a reference to some of the
ClassA objects created in ClassB. In ClassC I hook into the ClassA
events
with a foreach loop so that I hook each object. The code is something


这个:
类ClassC {
void SomeMethod()
{foreach(ClassA) ClassACollection中的项目
{
item.MyEvent + = new EventHandler(item_MyEvent);
}
}
}

类型的对象ClassC不断创建和删除,但它引用的
this:
class ClassC {
void SomeMethod()
{
foreach (ClassA item in ClassACollection)
{
item.MyEvent += new EventHandler(item_MyEvent);
}
}
}

Objects of type ClassC keep getting created and deleted, but the objects
ClassA的对象


会留在内存中。因此,每次我加载一个新的ClassC实例时,事件都会再次被钩住。我所看到的是

ClassA that it references stay in memory. Therefore, every time I load a
new instance of ClassC the event gets hooked again. What I''m seeing is


我点击了一次事件,但我最终在代码中引发它(
响应它)(item_MyEvent方法) )每次添加时我
I fire the event once but I end up getting it raised in the code that
responds to it (item_MyEvent method) for every time it was added when I


只有

希望它被抓到一次。

我怎么能确定我只添加每个
项目的事件处理程序一次?由于代码是在ClassC中,因此不允许检查ClassA.MyEvent,看看是否有东西已经连接到它。

我希望这是有道理的。创建一个repro案例在这里没有意义
因为它是我的应用程序逻辑导致问题。

谢谢。
want it to get caught once.

How can I be sure that I only add the handler to the event once for each
item? Since the code is in ClassC it''s not allowed to inspect the
ClassA.MyEvent to see if something''s already hooked to it.

I hope this makes sense. Creating a repro case wouldn''t make sense here
because it''s my application logic that''s causing the problem.

Thanks.




令人困惑的是你正在*减去* a * new *对象,但这是正确的语法。请记住,你要减去的''new''事件处理程序实际上(很可能)是对特定实例的成员函数的引用,所以它基本上只是说''这个成员函数实例不想再接收此事件。''告诉编译器,它需要的只是* ANY *对象,其类型是该成员函数的委托,并且它会理解 - 可能这是最不容易混淆的(虽然不仅仅是略微横向)实现这种语法的方式。

It IS confusing that you''re *subtracting* a *new* object, but that IS the correct syntax. Remember that the ''new'' event handler that you''re subtracting is actually (in all probability) a reference to a specific instance''s member function, so it''s basically just saying ''this member function of this instance doesn''t want to receive this event any more.'' To tell the compiler that, all it needs is *ANY* object whose type is a delegate to that member function, and it will understand - presumably this was the least confusing (albeit more than slightly lateral) way of implementing this syntax.


这篇关于代表和活动混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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