【问题标题】:Deleting child object from parent when something happens in child's internal thread当子对象的内部线程发生某些事情时,从父对象中删除子对象
【发布时间】:2013-08-27 21:33:53
【问题描述】:

假设我有ObjectA(classA),其中包含:

List<classB> bList;

现在让我们假设在每个objectB 中都有几个线程正在运行(它们不能从外部objectB 访问)threadB1 和threadB2。

现在,在此类列表的某个objectB 中,threadB2 发现objectBRemove==true。

发生这种情况时,我想终止此类对象的所有线程并将其从bList 中删除(我实际上想销毁此objectB)。

我想我可以在objectB 中发起一个事件,并订阅objectA 的方法来订阅这样的事件:

public void onObjectBRemove(object sender, EventArgs e)
{
    bList.Remove((classB) sender);
}

当在objectB 的事件上升之后调用它时,应该从列表中删除objectB。然后,垃圾收集器应该注意到objectB 变为未引用并因此将其删除,同时终止所有内部线程。

这应该有效吗?这是解决手头问题的合理方法吗?

【问题讨论】:

    标签: c# multithreading memory-management


    【解决方案1】:

    当在 objectB 的事件上升之后调用 this 时,应该从列表中删除 objectB。然后,垃圾收集器应该注意到 objectB 变为未引用并因此将其删除,同时终止所有内部线程。

    这将从列表中删除对象 - 但 List&lt;T&gt; 不是线程安全的,因此您需要同步(或线程安全集合,例如 ConcurrentBag&lt;T&gt;)。

    请注意,这不会终止正在运行的线程。如果您想停止正在运行的操作,您应该使用.NET's cooperative cancellation 并将CancellationTokenSource 设置为取消状态,此时您的线程可以正常退出。

    【讨论】:

    • 按照您的建议,我已将并发访问的列表替换为 ConcurrentBags。所以,除了手头的问题,我不应该在访问它们时不再使用 Monitor.TryEnter / Monitor.Exit 吗?截至目前,我正在阅读有关合作取消的部分,然后尝试实施您所说的。我会让你知道结果。
    • @CarloArnaboldi 是的 - 您可以从 ConcurrentBag&lt;T&gt; 添加/删除项目,无需锁定或 monitor.enter...
    • 只是一个简短的说明,让您知道我仅通过检查 TcpClient.Connected 值就设法关闭了其他线程。当然你不能这么建议,因为我没有公开我的程序的任何细节。无论如何,感谢您提供有用的建议,我会记住这一点以供将来参考。
    猜你喜欢
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多