对象运行线程A被线程B销毁时会发生什么?
我可能会很大误解这种线程场景,但这就是为什么我问。对象运行线程A被线程B销毁时会发生什么?
以下情况会发生什么(假设C#线程)?注意:这种情况被简化为核心问题,额外的功能被忽略。
我有2个对象,a和b,它们分别是类A和类B的实例; 'b'是'a'的成员。
'b'正在运行一个处理循环,并且还有其他一些活动不断做某些事情。在某一时刻,'b'检测到导致它将事件发送到'a'的情况。当'a'接收到该事件时,它执行以下代码:
void b_eventFoo()
{
b.UnhookEvents();//clears the delegate that truggered this event function
this.b = new B();
b.HookEvents(this);//connects the new b object to this A
}
旧的'B'对象会发生什么?原来的'b'仍然在做一些处理,触发事件的线程仍然可以执行。我不太了解线程是否足以预测此场景的结果。
它甚至有问题吗?
请让我知道我是否应该澄清任何事情。
在开始时,您有:
Thread1: [A1] -----field ----> [B1]
<--- event -----
您创建一个新的线程,运行在B1循环;这里的关键是代理和实例方法(使用期间)本身有一个对实例的引用(它是IL中的“arg0”);所以你必须:
Thread1: [A1] ---- field ----> [B1]
<--- event ----- ^
Thread2: ------------------------^
你然后解开事件并取消场:
Thread1: [A1] ---- field ----> [nil]
Thread2: --------------------> [B1]
并重新创建,并针对不同的实例rehook:
Thread1: [A1] ---- field ----> [B2]
<--- event -----
Thread2: --------------------> [B1]
所以:你的线程将继续处理反对[B1],但不再影响[A1]
原始B仍在运行,您只会失去对它的引用。
旧的B
仍在运行,仍然对A
有参考。由于A
不再知道这B
这可能是一个非常糟糕的情况。
如果可能的话,你应该尽量避免这样的循环引用,特别是当这样的操作顺序可能发生时。如果A
使用B
和B
使用A
,为什么他们不是一个类?他们非常紧密地联系起来,以便他们都可以访问彼此的成员。
B有参考A?你的意思是这个事件吗?在参考文件A必须丢失B之前,这是断开的。我不明白你看到的问题,请解释一下。 – CodeFusionMobile 2009-11-24 19:31:27
我已经编辑了OP来解开事件,就像我在真正的应用程序中做的那样,我忘了在之前加入这个事件。只有新的b有对b_eventFoo的引用 – CodeFusionMobile 2009-11-24 19:35:39
如果它是对B的唯一引用,它不会被删除b y垃圾收集器? – 2009-11-24 19:15:40
@valya,只有线程终止 - 线程处理程序维护一个引用,所以A的引用不是唯一的引用。 – Dathan 2009-11-24 19:17:45
valya:不,线程的堆栈也会持有对'b'的引用,至少是'this'。 – 2009-11-24 19:21:06