【问题标题】:Undesired termination of Thread created in Timer callback定时器回调中创建的线程意外终止
【发布时间】:2025-11-25 20:25:26
【问题描述】:

这就是我想做的:

  1. 有一个有一定间隔的计时器
  2. 在定时器回调代码中,如果满足某些条件,应该运行另一个线程

我已将我的代码放在一个由主窗体实例化的类中,并在方法调用时执行代码('StartSync()',参见示例代码)。

问题是代码运行了几秒钟但随后终止。我想我在做一些愚蠢的事情,但我真的看不出它是什么。感谢您对此提供的任何帮助。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace WindowsFormsApplication1
{
    class Syncer
    {
        static bool SYNC_IN_PROGRESS;

        public void StartSync()
        {
            SYNC_IN_PROGRESS = false;
            Timer timer = new Timer(timerCallback, null, 0, 1000);
        }

        public void timerCallback(Object stateInfo)
        {
            Debug.WriteLine("Sync?");

            if (!SYNC_IN_PROGRESS)
            {
                SYNC_IN_PROGRESS = true;

                Thread thSync = new Thread(new ThreadStart(sync));
                thSync.Start();
            }
        }

        void sync()
        {
            Debug.WriteLine("Syncing...");
            SYNC_IN_PROGRESS = false;
        }
    }
}

【问题讨论】:

  • 为什么不运行定时器回调中的代码,而不是新线程?
  • 你的线程,正如所写的,只会存活几微秒。用不可见的代码很难诊断问题。

标签: c# multithreading timer callback


【解决方案1】:

猜测Timer 仅保存在方法变量中; 对我来说听起来像 Timer 正在收集垃圾并最终确定,因此终止。我怀疑您应该在 字段 中保留该引用以防止收集。

顺便说一句-我怀疑这是这里的原因,但是在处理线程时,您应该虔诚地意识到从多个线程访问共享状态;例如:

  • 使用Monitor(又名lock
  • 适当使用volatile
  • Interlocked 合适时

您当前对static bool 的访问可能可以正常工作,但是...

【讨论】:

  • 不,回调让它活着。只要 Syncer 对象仍然被引用。
【解决方案2】:

试试这种更简洁的方法

    static volatile bool SYNC_IN_PROGRESS; 
    static thread syncPoll; 

    public void StartSync() 
    { 
        SYNC_IN_PROGRESS = false; 
        syncPoll = new Thread(sync);
        syncPoll.Start();
    } 

    void sync() 
    { 
        while (true)
        {
             Debug.WriteLine("Sync?");
             if (SYNC_IN_PROGRESS) Debug.WriteLine("Syncing..."); 
             Thread.Sleep(1000);
        }
    } 

它与您尝试对当前代码执行的操作相同 :) 但不使用计时器

【讨论】:

  • 确实,这段代码更干净,加上一些小的补充,这个解决方案完成了我想要实现的目标。我想 Mitch(上图)建议的方法也可以解决问题,例如删除第二个线程并将所有代码放入计时器回调中。虽然我对原始代码中发生的事情仍然有些困惑。
【解决方案3】:

这就是我所做的,它似乎工作得很好

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            StartSync();
        }

        static bool SYNC_IN_PROGRESS;

        public void StartSync()
        {
            SYNC_IN_PROGRESS = false;
            System.Threading.Timer timer = new System.Threading.Timer(timerCallback, SYNC_IN_PROGRESS, 0, 1000); 


        }

        public void timerCallback(Object stateInfo)
        {
            Debug.WriteLine("Sync?");

            if (!(bool)stateInfo)
            {
                SYNC_IN_PROGRESS = true;

                Thread thSync = new Thread(new ThreadStart(sync));
                thSync.Start();
            }
        }

        void sync()
        {
            Debug.WriteLine("Syncing...");
            SYNC_IN_PROGRESS = false;
        }
    }

【讨论】:

  • 恐怕这段代码的行为和我的一样(至少在我的机器上);它运行 5-10 秒然后停止。
  • 有趣的是我跑了大约 5 分钟。我放弃了等待。大声笑