gpt4 book ai didi

c# - 删除对对象的引用时结束线程

转载 作者:行者123 更新时间:2023-11-30 15:24:51 25 4
gpt4 key购买 nike

我有一个 List 对象,有时会生成一个线程并维护一个终止所述线程的 bool;然而,当通过 List.clear() 清除父级 List 时,这些对象的引用偶尔会被删除。

这显然会导致我无法再终止的孤立线程。

我知道我可以通过确保在清除 List 之前取消所有线程来解决问题,但是我很好奇是否有可能确定对生成线程的对象的引用被删除。

基本上我有这个通用结构:

List<Foo> myFoos = new List<Foo>();

class Foo {
public bool keepThreadAlive = false;

public void StartThread () {
Thread newThread = new Thread(() => {
while(keepThreadAlive) {
// Do stuff until told to stop
}
});
}
}

偶尔会清除 myFoos

是否有可能从未命名线程中检测到对 Foo 的引用丢失并终止 while

最佳答案

I'm curious if it's possible to determine if the reference to the object that spawned the thread is dropped

不是,不是直接意义上的。 .NET 有一个 WeakReference<T>类可以跟踪对象是否仍被任何 其他变量引用,但在这种情况下,您不太可能创建列表包含引用该对象的唯一变量的情况。 IE。只要任何变量仍然引用该对象,WeakReference<T> object 将指示该对象仍然存在。

在此处提供的代码示例中,您的线程正在列表中引用的对象内部运行代码。您正在使用匿名方法,但假设代码使用对象本身,则匿名方法将包含在本身引用该对象的匿名类中,从而导致第二个持久引用。

您可以尝试通过将线程代码放入静态方法来绕过它,其中对象引用本身是从 WeakReference<T> 中检索的对象(如果可用)(并且线程将在不可用时退出)。但是假设线程以某种规律性使用该对象,静态方法中的代码很可能会使该对象保持事件状态足够长的时间,以至于 GC 没有机会注意到它处于未使用状态。

作为评论者user2864740请注意,您还可以采用其他更明确的方法。我不太喜欢轮询列表的想法(如果列表很大,这可能会特别糟糕,而且在任何情况下都是浪费),但如果你能够使用一个可观察的列表,比如 ObservableCollection<T> ,那可以工作。为此,您必须订阅 CollectionChanged事件并适本地处理它:

myFoos.CollectionChanged += (sender, e) =>
{
if (e.Action == NotifyCollectionChangedAction.Remove ||
e.Action == NotifyCollectionChangedAction.Replace)
{
foreach (Foo foo in e.OldItems)
{
foo.CancelThread(); // or whatever
}
}
};

请注意,以上只是基本思路。您的问题中没有足够的上下文来知道它是否足够,或者例如,您可能需要做一些特殊的事情来处理添加到集合中的新项目(通过 AddReplace 操作)。

就我个人而言,如果您知道这些项目只会在您清除列表时“丢失”,那么最好的方法就是您已经知道的方法:只需取消列表中对象所代表的所有任务在清除列表之前列出。

关于c# - 删除对对象的引用时结束线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32238106/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com