Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 定时器类在程序结束前未触发_C#_Multithreading_Timer - Fatal编程技术网

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

C# 定时器类在程序结束前未触发,c#,multithreading,timer,C#,Multithreading,Timer,因此,我试图在这里修改Sriram Sakthivel发布的代码块: 公共类程序 { 静态布尔签入=false; 公共静态无效检查周期() { checkIn=SynchronousSocketClient.StartClient(); 如果(签入==false) { //使用TimeSpan构造函数指定: //…天,小时,分钟,秒,毫秒。 时间跨度=新的时间跨度(00,00,30); //设置定时器(span); DateTime current=DateTime.Now; TimeSpan

因此,我试图在这里修改Sriram Sakthivel发布的代码块:

公共类程序
{
静态布尔签入=false;
公共静态无效检查周期()
{
checkIn=SynchronousSocketClient.StartClient();
如果(签入==false)
{
//使用TimeSpan构造函数指定:
//…天,小时,分钟,秒,毫秒。
时间跨度=新的时间跨度(00,00,30);
//设置定时器(span);
DateTime current=DateTime.Now;
TimeSpan triggerTime=current.TimeOfDay+span;
设置计时器(触发时间);
}
如果(签入==true)
{
//做一些处理
}
}
公共静态无效设置计时器(TimeSpan alertTime)
{
//DateTime current=DateTime.Now;
//TimeSpan timeToGo=alertTime-current.TimeOfDay;
TimeSpan timeToGo=警报时间;
Console.WriteLine(“签入时间:“+timeToGo”);
if(timeToGo
{
Console.WriteLine(“运行签入循环”);
检查周期();
},null,timeToGo,Timeout.InfiniteTimeSpan);
}
公共静态int Main(字符串[]args)
{
检查周期();
Console.WriteLine(“到达程序结束”);
Console.ReadLine();
返回0;
}
}
但是,我没有指定运行的确切时间,而是尝试在当前时间上加上30分钟,以使客户端服务在尝试再次连接之前保持x分钟的活动时间。现在,为了简单/测试起见,如果无法连接到服务器,我将其设置为每30秒运行一次checkInCycle

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


你知道为什么会这样吗?另外,我知道在再次检查之前,我可以将主线程休眠x分钟,但是客户端可能会休眠数小时,因此我听说计时器效率更高,是这样吗

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

在上面的参考(备注下的第二个注释)中,文档说明了必须维护一个参考(与所有托管代码一样),以使其不被垃圾收集器处理

只要使用计时器,就必须保留对它的引用。与任何托管对象一样,当没有对计时器的引用时,计时器将接受垃圾收集。计时器仍处于活动状态这一事实并不妨碍对其进行收集

保持这个简单程序的方法是,在
main()
函数中的
checkInCycle()
函数调用之后直接使用并执行
Wait()
。然后,当您想继续时,
Pulse()

如果您对执行异步调用或在多线程环境中操作的更深入主题感兴趣,您可能需要进一步阅读线程同步或并发


*为澄清而编辑。

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

在上面的参考(备注下的第二个注释)中,文档说明了必须维护一个参考(与所有托管代码一样),以使其不被垃圾收集器处理

只要使用计时器,就必须保留对它的引用。与任何托管对象一样,当没有对计时器的引用时,计时器将接受垃圾收集。计时器仍处于活动状态这一事实并不妨碍对其进行收集

保持这个简单程序的方法是,在
main()
函数中的
checkInCycle()
函数调用之后直接使用并执行
Wait()
。然后,当您想继续时,
Pulse()

如果您对执行异步调用或在多线程环境中操作的更深入主题感兴趣,您可能需要进一步阅读线程同步或并发


*为澄清而编辑。

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

此外,根据您修改
SetupTimer
的方式,您不应添加当前时间,而应直接传递重试时间。否则您必须等待几个小时:-)

您的计时器可能会被垃圾收集,因为它是一个局部变量,请将其设置为类级变量/字段。您的触发时间应该是
span
,不要将一天中的时间添加到其中。我很抱歉。您需要保留计时器的引用,以防止它被垃圾收集。我在原始帖子中更新了我的答案,以反映这一变化。您的计时器可能正在被垃圾收集,因为它是一个局部变量,请将其设置为类级变量/字段。您的触发时间应为
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;

    }
}