【问题标题】:What happens when object running thread A is destroyed by thread B?当运行线程 A 的对象被线程 B 销毁时会发生什么?
【发布时间】:2009-11-24 19:10:49
【问题描述】:

我可能对这种线程场景有很大的误解,但这就是我要问的原因。

在以下情况下会/可能发生什么(假设 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”仍在进行一些处理,并且触发事件的线程可能仍在执行。我对线程的理解不够深入,无法预测这种情况的结果。

这有关系吗?

如果我需要澄清任何事情,请告诉我。

【问题讨论】:

    标签: c# multithreading thread-safety


    【解决方案1】:

    一开始,你有:

    Thread1: [A1] -----field ----> [B1]
                  <--- event -----
    

    你创建一个新线程,在 B1 上运行一个循环;这里的关键是委托和实例方法(在使用期间)自身对实例有引用(在 IL 术语中是“arg0”);所以你有:

    Thread1: [A1] ---- field ----> [B1]
                  <--- event -----   ^
    Thread2: ------------------------^
    

    然后您取消挂钩事件并取消该字段:

    Thread1: [A1] ---- field ----> [nil]
    
    Thread2: --------------------> [B1]
    

    然后针对不同的实例重新创建和重新挂钩:

    Thread1: [A1] ---- field ----> [B2]
                  <--- event -----
    
    Thread2: --------------------> [B1]
    

    所以:您的线程继续处理 [B1],但不再影响 [A1]

    【讨论】:

      【解决方案2】:

      原来的 B 还在运行,你只会失去对它的引用。

      【讨论】:

      • 如果它是对B的唯一引用,那它不会被垃圾收集器删除吗?
      • @valya,只有在线程终止时 - 线程处理程序维护一个引用,所以 A 的引用不是唯一的。
      • valya:不,线程的堆栈也会包含对“b”的引用,至少是this
      【解决方案3】:

      旧的B 仍在运行,并且仍然有对A 的引用。由于A 不再知道这个B,这可能是一个非常糟糕的情况。

      如果可能的话,你应该尽量避免这样的循环引用,尤其是当这样的操作顺序可能发生时。如果A 使用BB 使用A,为什么它们不是一个类?它们之间的耦合相当紧密,因此它们都可以访问彼此的成员。

      【讨论】:

      • B 引用了 A?你是说事件吗?在 A 必须对 B 的引用丢失之前断开连接。我不明白你看到的问题,请解释一下。
      • 我已经编辑了 OP 以解开事件,就像我在实际应用程序中所做的那样,我之前忘了包括这个。只有新的 b 引用了 b_eventFoo
      猜你喜欢
      • 2011-09-06
      • 1970-01-01
      • 2021-05-27
      • 2014-09-18
      • 1970-01-01
      • 2017-11-18
      • 2013-03-20
      • 2021-11-16
      • 1970-01-01
      相关资源
      最近更新 更多