C#System.Threading.Timer递归更新

C#System.Threading.Timer递归更新,c#,multithreading,timer,C#,Multithreading,Timer,我有一个计时器,每15秒调用一个函数,前5次有效,但第6次无效,即使是创建的,有什么想法吗 处理时间可能会超过15秒,如果是这样,线程A可能正在处理数据,而线程B发出新的数据请求。在线程A的处理完成之前,线程B无法启动 const int DATAREFRESH = 15000; void RequestUpdate() { // Some data processing goes here Console.WriteLine("Update"); // Set th

我有一个计时器,每15秒调用一个函数,前5次有效,但第6次无效,即使是创建的,有什么想法吗

处理时间可能会超过15秒,如果是这样,线程A可能正在处理数据,而线程B发出新的数据请求。在线程A的处理完成之前,线程B无法启动

const int DATAREFRESH = 15000;

void RequestUpdate()
{
    // Some data processing goes here
    Console.WriteLine("Update");

    // Set the timer
    Timer t = new Timer(new TimerCallback(TimeOutCallback), null, DATAREFRESH, Timeout.Infinite);
}

private void TimeOutCallback(object state)
{
    RequestUpdate();
}
在输出窗口中,“更新”显示5次,然后什么也不显示。它还没有冻结,我看到~8个线程在最后一次“更新”后终止


如何使其无限工作?

从回调中实例化一个新计时器似乎很奇怪。更现实的例子是,您正在计时器回调中执行工作。此外,您似乎错误地调用了
计时器
构造函数。如果希望以固定的间隔(在您的情况下为15秒)执行回调,可以使用以下方法:

const int DATAREFRESH = 15000;
private Timer _timer;

void RequestUpdate()
{
    // Set the timer
    _timer = new Timer(TimeOutCallback, null, 0, DATAREFRESH);
}

private void TimeOutCallback(object state)
{
    // Some data processing goes here
    Console.WriteLine("Update");
}

还请注意,我如何反转传递给计时器的参数,使其每15秒执行一次回调。

从回调中实例化一个新计时器似乎很奇怪。更现实的例子是,您正在计时器回调中执行工作。此外,您似乎错误地调用了
计时器
构造函数。如果希望以固定的间隔(在您的情况下为15秒)执行回调,可以使用以下方法:

const int DATAREFRESH = 15000;
private Timer _timer;

void RequestUpdate()
{
    // Set the timer
    _timer = new Timer(TimeOutCallback, null, 0, DATAREFRESH);
}

private void TimeOutCallback(object state)
{
    // Some data processing goes here
    Console.WriteLine("Update");
}

还要注意我是如何反转传递给计时器的参数的,以便它每15秒执行一次回调。

是的,垃圾收集器已删除计时器对象。这个问题是通过将计时器引用声明为局部变量开始的。RequestUpdate()方法退出后,没有对计时器的引用。甚至回调也不提供引用,这有点不寻常,但它与具有静态回调方法并避免泄漏的计时器保持一致

简单的解决方法是将其作为类的字段:

private Timer dataRefreshTimer;

void RequestUpdate()
{
    dataRefreshTimer = new Timer(new TimerCallback(TimeOutCallback), null, 0, DATAREFRESH);
}
它确保计时器至少与包含回调方法的类一样长


值得注意的是System.Timers.Timer类没有同样的问题。CLR确保这些计时器在启用期间一直处于引用状态。但是不要使用它,否则它不是一个很好的计时器。

是的,垃圾收集器已经删除了计时器对象。这个问题是通过将计时器引用声明为局部变量开始的。RequestUpdate()方法退出后,没有对计时器的引用。甚至回调也不提供引用,这有点不寻常,但它与具有静态回调方法并避免泄漏的计时器保持一致

简单的解决方法是将其作为类的字段:

private Timer dataRefreshTimer;

void RequestUpdate()
{
    dataRefreshTimer = new Timer(new TimerCallback(TimeOutCallback), null, 0, DATAREFRESH);
}
它确保计时器至少与包含回调方法的类一样长



值得注意的是System.Timers.Timer类没有同样的问题。CLR确保这些计时器在启用期间一直处于引用状态。但是不要用它,否则它不是一个很好的计时器。

请使用一个描述您试图解决的问题的标题。您使用的是哪个
timer
类?为什么不创建一个计时器实例并在回调中重置它?请使用一个描述您试图解决的问题的标题。您是哪个
timer
类使用?为什么不创建一个计时器实例并在回调中重置它?@craig1231,注意我是如何反转参数的:
new timer(TimeOutCallback,null,0,DATAREFRESH)。现在计时器将定期执行回调。这看起来是正确的,但我已经更新了上面的问题。@craig1231,我不理解你的更新。在前面的评论中,您谈到了计时器的无限处理,现在您开始讨论一些线程B发送一些请求(什么请求?)关于一些数据(什么数据?)。我完全不知道你想做什么,你的问题是什么。也许如果你提供一个更现实的例子,你的问题对我来说会更有意义。这个答案没有解决OP的关键问题,计时器仍然停止滴答作响。@HansPassant,我必须承认我完全不知道OP现在的问题是什么。也许你是对的。我不知道我们要解决什么问题,因为我们没有一个真实的例子和上下文。@craig1231,注意我是如何颠倒参数的:
new Timer(TimeOutCallback,null,0,DATAREFRESH)。现在计时器将定期执行回调。这看起来是正确的,但我已经更新了上面的问题。@craig1231,我不理解你的更新。在前面的评论中,您谈到了计时器的无限处理,现在您开始讨论一些线程B发送一些请求(什么请求?)关于一些数据(什么数据?)。我完全不知道你想做什么,你的问题是什么。也许如果你提供一个更现实的例子,你的问题对我来说会更有意义。这个答案没有解决OP的关键问题,计时器仍然停止滴答作响。@HansPassant,我必须承认我完全不知道OP现在的问题是什么。也许你是对的。我只是不知道我们在这里试图解决什么问题,因为我们没有一个真实的示例和上下文。如果计时器在一个静态类中设置为静态变量,这好吗?如果计时器在一个静态类中设置为静态变量,这好吗?