定时器类在程序结束前未触发

时间:2015-09-02 15:07:26

标签: c# multithreading timer

所以我试图修改Sriram Sakthivel发布的代码块:

C#: How to start a thread at a specific time

public class Program
{
    static Boolean checkIn = false;

    public static void checkInCycle()
    {
        checkIn = SynchronousSocketClient.StartClient();

        if(checkIn == false)
        {
            // Use TimeSpan constructor to specify:
            // ... Days, hours, minutes, seconds, milliseconds.
            TimeSpan span = new TimeSpan(00, 00, 30);

            //SetUpTimer(span);
            DateTime current = DateTime.Now;
            TimeSpan triggerTime  = current.TimeOfDay + span;

            SetUpTimer(triggerTime);
        }
        if(checkIn == true)
        {

            //Do some processing 
        }



    }

    public static void SetUpTimer(TimeSpan alertTime)
    {
        //DateTime current = DateTime.Now;
        //TimeSpan timeToGo = alertTime - current.TimeOfDay;

        TimeSpan timeToGo = alertTime;
        Console.WriteLine("Checking in at: " + timeToGo);

        if (timeToGo < TimeSpan.Zero)
        {
            return; //time already passed
        }
        System.Threading.Timer timer = new System.Threading.Timer(x =>
        {
            Console.WriteLine("Running CheckIn Cycle");
            checkInCycle();

        }, null, timeToGo, Timeout.InfiniteTimeSpan);

    }

    public static int Main(String[] args)
    {
        checkInCycle();

        Console.WriteLine("End of Program Reached");
        Console.ReadLine();

        return 0;

    }
}

然而,我没有指定运行的确切时间,而是尝试在当前时间上添加30分钟,以尝试在尝试再次连接之前使客户端服务保持活动x分钟。现在,为了简单/测试,我将它设置为每30秒运行一次checkInCycle,如果它无法连接到服务器。

首先检查SynchronousSocketClient.StartClient();如果服务器关闭,则成功返回false,并且将进入if(checkIn == false)循环 - 但是,在设置定时器后,它继续处理主循环的其余部分,并在结束时等待而不触发并重新安排计时器。

有关为何发生这种情况的任何想法?另外我理解我可以在再次重新检查之前睡觉主线程x分钟,但客户端可能睡了几个小时,因此我听说定时器更有效率,是这样的吗?

2 个答案:

答案 0 :(得分:4)

这种情况正在发生,因为在执行main()方法结束时,您将失去对System.Threading.Timer的引用。 new System.Threading.Timer调用在等待运行代码时不会阻塞主线程。

在上面的参考文献(备注下的第二个注释)中,文档说明必须维护引用(与所有托管代码一样),以便垃圾收集器不要处理它。 / p>

  

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

如果您使用System.Threading.Monitor并在Wait()函数中的checkInCycle()函数调用后直接执行main(),则可以保留此简单程序的方式。如果您想继续,请Pulse()

如果您对有关执行异步调用或在多线程环境中运行的任何更深入的主题感到好奇,您可能希望进一步了解线程同步或并发性。

*编辑以澄清。

答案 1 :(得分:1)

除了Andrew的答案,您修改SetupTimer的方式之外,您不应该添加当前时间并直接传递重试时间。否则你必须等几个小时:-)