【问题标题】:The thread has exited with code 0 in Windows Forms线程已在 Windows 窗体中以代码 0 退出
【发布时间】:2013-04-17 07:47:39
【问题描述】:

我在 Windows 窗体中退出线程时遇到问题。

我有经典的 Windows 窗体,它正在运行。我每隔一段时间都需要做一些事情,所以我补充说:

TimerCallback timerDelegate = new TimerCallback(this.TryDoSomething);
int period = 10 * 1000; // to miliseconds
System.Threading.Timer stateTimer = new System.Threading.Timer(timerDelegate, null, period, period);

方法 DoSomething 由几个线程(主线程和这个计时器)调用,所以我是这样介绍的:

private void TryDoSomething(object o)
        {
            lock (tryDoSomethingMutex)
            {
                if (this.dataGridView1.InvokeRequired)
                {
                    RefreshCallback d = new RefreshCallback(DoSomething);
                    this.Invoke(d, new object[] { o });
                }
                else
                {
                    this.DoSomething(o);
                } 
            }
        }

一切正常,直到我的计时器线程刚刚退出并显示消息:

The thread 0x2798 has exited with code 0 (0x0).

同样的事情发生在我的 FileSystemWatcher 上,它也调用了 DoSomething 方法。 这两个事件都是独立的,并且在随机时间退出(至少我没有找到任何规则)

造成这种情况的原因是什么,我该如何预防?

【问题讨论】:

  • 这不是错误,它只是表明线程已完成执行。
  • 直到你的时间线程退出?所以不是说要退出吗?设置dueTime的不是你吗?
  • 这就是问题所在——我不是。计时器被设置为每隔一段时间做一些事情,然后在随机时间突然退出(但没有任何错误)。

标签: c# .net multithreading winforms


【解决方案1】:

如果您不保留对计时器对象的引用,它将被垃圾回收。

查看您发布的代码,您似乎并没有保留引用。您需要将其设置为包含类中的字段,而不是局部变量。

如果您在长时间运行的方法开始时声明它并且不在该方法的后面引用它,则计时器也可以被垃圾收集。

您可以通过在方法 as described here 的末尾附近添加 GC.KeepAlive(timer); 来解决该特定问题。

【讨论】:

  • 当然这是正确答案,谢谢!现在,当我想到它时,它似乎很明显。误导我的是这样一个事实,即线程通常需要一分钟多的时间才能退出,而声明它的方法在“很久”之前就结束了。所以花了大约一分钟(有时甚至两分钟或更长时间)GarbageCollector 才发现它是垃圾并且应该被丢弃?为什么这么久?
  • 垃圾收集器往往不会经常运行,除非内存越来越少,以减少开销;我想这就是为什么花了这么长时间。
  • 这是有道理的。谢谢:)
  • 为了完全准确,我真的应该说“第 2 代垃圾收集往往不会经常运行”。第 0 代经常运行,但计时器可能会一直存活到第 2 代。
【解决方案2】:

听起来 Timer 正在收集垃圾。使其成为表单的实例变量,以便您可以保留引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多