2

目前我在 Callaback 过程中有一个 For 循环:

private void InitializeComponent()
{

var timer = new System.Threading.Timer(TimerProc, null, 60000, 60000);

}

public void TimerProc(object state)
{

    for (int i = 0; i <= 6; i++)
    {
        //Do something here
    }

}

TimerProc 只触发一次,尽管我将它设置为每 60000 毫秒重复一次。看起来循环内的操作在第一次完成后不再执行。

但是,如果我删除 For 循环并执行一些其他操作,例如打印到控制台行或写入文本文件,则 TimerProc 会按预期重复。

为什么会出现这种情况,为什么回调过程中的循环会在初始触发后阻止它执行?

我通过使用 while(true) 无限循环并使用 Thread.Timer 在 x 毫秒后暂停进程来解决问题。

我的带有 while 循环的新可视化代码如下所示:

private void InitializeComponent()
{

processthread = new Thread(new ThreadStart(DoSomething));
processthread.Start();

}

public void DoSomething()

{

  while(true)
  {
    for (int i = 0; i <= 6; i++)
    {
           //do something here

    }
    Thread.Sleep(5000);
  }

}

我只想知道为什么 System.Thread.Timer 中的回调过程不能处理循环。

干杯,

斯坦利

4

2 回答 2

1

从您包含在问题中的代码来看,您似乎没有存储对timer任何地方的引用。我可能是错的,但我的猜测是您没有看到重复的回调,因为计时器对象本身已被垃圾收集。将对计时器的引用分配给寿命更长的变量(即字段),我敢打赌这将解决问题。

换句话说,我认为for循环与您所看到的没有任何关系(我不是在质疑证据,只是提出这是巧合而已)。

为了检验我的假设,我创建了以下非常简单的 Windows 窗体应用程序:

using System;
using System.Threading;
using System.Windows.Forms;

using Timer = System.Threading.Timer;

public class Program
{
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new TestForm());
    }
}

class TestForm : Form
{
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        var timer = new Timer(TimerProc, null, 1000, 1000);
    }

    public void TimerProc(object state)
    {
        for (int i = 0; i <= 6; i++)
        {
            Console.WriteLine(DateTime.Now.ToLongTimeString());
        }
    }
}

我看到当前时间在控制台上打印了三十多秒;然后它停止了。

相反,以下更改似乎可以解决该问题。

class TestForm : Form
{
    // Note: declare a field to store a reference to the timer.
    Timer timer;

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        this.timer = new Timer(TimerProc, null, 1000, 1000);
    }

    // ...
}

进行上述更改后,我再次启动程序,计时器继续触发了几分钟。

于 2012-07-23T04:06:08.307 回答
0

更新:在与Dan Tao讨论后,由于缺乏参考,这可能是 GC 问题。添加参考解决了这个问题[取消注释第 8 行和第 20 行]。问题中“for循环”的存在可能会导致收集 - 可能是通过生成垃圾来解释为什么在这个特定情况下删除它并用更简单的 LOC 替换它对你有用。

using System;
using System.Threading;

namespace SO_TimerTroubles
{
    class Program
    {
        //static Timer t;
        static void Main(string[] args)
        {
            StartTimer();  //Works fine.
            Console.WriteLine("Press Enter to BeginGC");
            Console.ReadLine();
            GC.Collect();  //Timer stops.
            Console.ReadLine();
        }

        public static void StartTimer()
        {
            //t =
            new Timer(TimerProc, null, 1000, 1000);
        }

        static public void TimerProc(object state)
        {
            Console.WriteLine("Timer Called");
            for (int i = 0; i < 5; i++)
            {
            }
        }
    }
}

[原始答案] 以下工作正常 - 我怀疑错误在其他地方。

class Program
    {
        static void Main(string[] args)
        {

            var timer = new Timer(TimerProc, null, 1000, 1000);

            Console.ReadLine();
        }

        static public void TimerProc(object state)
        {
            Console.WriteLine("Called");
            for (int i = 0; i <= 6; i++)
            {
                Console.WriteLine(i);
            }

        }
    }
于 2012-07-23T04:06:19.613 回答