System.Threading.Timer 在 25-30 次后停止 [重复]

Posted

技术标签:

【中文标题】System.Threading.Timer 在 25-30 次后停止 [重复]【英文标题】:System.Threading.Timer stops after 25-30 times [duplicate] 【发布时间】:2020-02-09 06:45:21 【问题描述】:
        var startTimeSpan = TimeSpan.Zero;
        var periodTimeSpan = TimeSpan.FromSeconds(5);

        var timer = new System.Threading.Timer((e) =>
        
            limit = helper.CheckLimit();
        , null, startTimeSpan, periodTimeSpan); 

在我的 C# 应用程序中,计时器只能工作 30 次。之后停止。为什么,我不知道。哪里错了?

这是我的 CheckLimit 助手;

  public bool CheckLimit()
    
        try
        
            var queryParams = new NameValueCollection()
            
                 "p", "check_limit" ,
            ;

            string response = this.ApiCall(queryParams);
            dynamic json_response = JsonConvert.DeserializeObject(response);
            if (json_response.success == true)
            
                return true;
            
            else
            
                return false;
            
        
        catch (Exception)
        
            return false;
        
    

【问题讨论】:

可以分享一下周边的代码吗?特别是helper.CheckLimit() 我分享了,谢谢。 var timer 在哪里?以某种方式? 你是否保持对计时器的引用,以确保它不会被垃圾收集?从文档中:只要您使用 Timer,就必须保留对它的引用。与任何托管对象一样,当没有对 Timer 的引用时,它会受到垃圾回收的影响。计时器仍然处于活动状态这一事实并不能阻止它被收集。 你怎么知道定时器已经停止工作了?您是否有一些代码正在检查以确保实际调用了回调? 【参考方案1】:

我的赌注是 Jon 的建议,我将在此基础上抄袭一个答案

Timer Class (System.Threading) 的文档包含以下注释。

只要您使用 Timer,就必须保留对它的引用。与任何托管对象一样,当没有对 Timer 的引用时,它会受到垃圾回收的影响。 Timer 仍然处于活动状态这一事实并不能阻止它被收集。

var timer 表明您可能无法保持引用。您可以将其设置为在应用程序的整个生命周期内保持活动状态的对象的字段。

高级说明new System.Threading.Timer(TimerCallback callback) 构造函数将this 用于state 对象,这使计时器在整个GC.Collects 中保持活动状态(请参阅下文了解更多信息)。


示例

这是一个说明问题的完整示例。

输出

A
B
A
B
B
A
GC Collected
B
B
B

代码

using System;
using System.Threading.Tasks;

class TimerExperiment

    System.Threading.Timer timer; 
    public TimerExperiment() 
        StartTimer("A"); // Not keeping this timer
        timer = StartTimer("B"); // Keeping this timer
    

    static System.Threading.Timer StartTimer(string name) 
        return new System.Threading.Timer(_ =>
        
            Console.WriteLine($"name");
        , null, dueTime: TimeSpan.Zero, period: TimeSpan.FromSeconds(1));
    



class Program

    static async Task Main(string[] args)
    
        var withTimers = new TimerExperiment();

        await Task.Delay(TimeSpan.FromSeconds(2));
        GC.Collect();
        Console.WriteLine("GC Collected");
        Console.ReadLine();
    



搅浑水

System.Threading.TimerTimer(TimerCallback callback) 构造函数(不采用dueTime 和其他的构造函数)使用this 代替state,这意味着计时器将保留对自身的引用,这意味着它将在垃圾收集中幸存下来。

public Timer(TimerCallback callback)

    (...)
    TimerSetup(callback, this, (UInt32)dueTime, (UInt32)period, ref stackMark);

示例 2

计时器“C”是使用Timer(TimerCallback callback) 创建的,它一直在运行。

输出

A
B
C
A
B
C
GC Collected
B
C
C
B
B
C

代码

class TimerExperiment

    System.Threading.Timer timerB;

    public TimerExperiment()
    
        StartTimer("A"); // Not keeping this timer
        timerB = StartTimer("B"); // Keeping this timer
        StartTimer2("C"); // Not keeping this timer
    

    static System.Threading.Timer StartTimer(string name) 
        return new System.Threading.Timer(_ =>
        
            Console.WriteLine($"name");
        , null, dueTime: Delay(name), period: TimeSpan.FromSeconds(1));
    

    static System.Threading.Timer StartTimer2(string name)
    
        //Create the timer using the constructor which only takes the callback
        var t = new System.Threading.Timer( _ => Console.WriteLine($"name"));
        t.Change(dueTime: Delay(name), period: TimeSpan.FromSeconds(1));
        return t;
    

    static TimeSpan Delay(string name) 
            => TimeSpan.FromMilliseconds(Convert.ToInt64(name[0])*10);



class Program

    static async Task Main(string[] args)
    
        var withTimers = new TimerExperiment();

        await Task.Delay(TimeSpan.FromSeconds(2));
        GC.Collect();
        Console.WriteLine("GC Collected");
        Console.ReadLine();
    

【讨论】:

你能给我示例代码吗?因为我是 C# 新手 是的,当我回到我的电脑前,我会破解一些示例代码。

以上是关于System.Threading.Timer 在 25-30 次后停止 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

System.Windows.Forms.TimerSystem.Timers.TimerSystem.Threading.Timer

为啥 System.Timers.Timer 能在 GC 中存活,而 System.Threading.Timer 不能?

System.Threading.Timer 在 25-30 次后停止 [重复]

System.Threading.Timer:它为啥讨厌我?

System.Threading.Timer 杀死 PowerShell 控制台

定时器:Timer:System.Threading.Timer类(转)