【问题标题】:Threads and garbage collection线程和垃圾收集
【发布时间】:2012-06-27 19:26:43
【问题描述】:

我有一个 Windows 服务,它连续运行并创建一些线程来做一些工作。我想确保这些线程被妥善处理(完成后收集垃圾。

但是,我还希望能够定期检查它们是否还活着,如果存在则终止它们。不过,我知道我不能保留对它们的任何引用,因为那样它们就不会被垃圾回收。

是否有替代方法来检查用户定义线程的存在/状态?我在想也许像下面这样使用WeakReference:(我现在不能完全测试,或者我自己测试一下)

List<WeakReference> weakReferences;
Thread myThread = new Thread(() => Foo());
WeakReference wr = new WeakReference(myThread);
weakReferences.Add(wr);  //adds a reference to the thread but still allows it to be garbage collected
myThread.Start();
myThread = null;  //get rid of reference so thread can be garbage collected

然后在我的 onTimeElapsed 事件开始时(每 5 分钟运行一次):

foreach(WeakReference wr in weakReferences)
{
    Thread target = wr.Target as Thread;  //not sure if this cast is really possible
    if(target.IsAlive && otherLogic)
    {
         target.Abort();
    {
}

但我不确定 WeakReference 究竟是如何工作的。有关如何正确执行此操作的任何想法?

【问题讨论】:

  • 确保线程被清理的最简单方法就是确保它们的工作最终终止(成功或其他)。我很好奇在什么情况下会产生一个线程并且你想在它工作完成之前清理它。
  • 无论如何,中止线程是一个非常糟糕的主意。这通常会奏效,但您在这里安装了定时炸弹。

标签: c# multithreading garbage-collection weak-references


【解决方案1】:

myThread 是方法变量吗?还是……?

在大多数情况下,线程在可能的情况下简单地被垃圾收集。如果myThread 是方法变量,则无需将myThread 设置为null,因为当时该变量不存在

然而,我要注意线程实际上是非常昂贵的对象(单独分配堆栈是很痛苦的)。如果可能的话,我建议使用ThreadPool(如果每个项目都是短暂的)或定制的工作队列(如果更长),可能有多个工作人员为单个队列服务。

至于终止/中止线程......这从不是个好主意;你不知道此时线程在做什么。在那之后,可能你的整个过程注定要失败。如果可能完全,请考虑让工作人员偶尔检查“中止”标志。如果不可能,请考虑在一个单独的流程中完成这项工作。一个进程比一个线程还要昂贵,但它的优点是它是隔离的;你可以在不影响自己的情况下杀死它。当然,你仍然可以破坏它正在处理的任何文件,等等......

坦率地说,我考虑中止线程的主要时间是如果我的进程已经死亡,我正试图尽快让它摆脱痛苦。

【讨论】:

  • 要为 Marc 的答案添加更多内容,您可以查看 Task&lt;T&gt; 类。它支持取消(如果我在 .NET 3.5 中是正确的)和进度报告(如果我在 .NET 4.5 中是正确的)。
  • @oleksii 确实如此,但取消与任意中止相同;为了使取消正常工作,代码本身需要是可取消的
【解决方案2】:

使用线程池。不要自己产生线程,也不要发明轮子。

【讨论】:

  • 但我喜欢我的轮子有四个侧面!
猜你喜欢
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
相关资源
最近更新 更多