比较DateTime不起作用

时间:2011-03-10 15:01:35

标签: c#

我正在创建一个记录计算机进程的程序,然后从那个初始时间开始,每隔X分钟,另一个日志保存在一个文本文件中。我已经写了文本文件,一切都很顺利。我似乎无法让DateTime正常工作,或者我误解了它的用途。

DateTime firstTime = DateTime.Now; 

Process[] processlist = Process.GetProcesses();

foreach (Process theprocess in processlist)
{
    sw.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
sw.WriteLine(firstTime);


DateTime now = DateTime.Now.AddMinutes(1);
sw.WriteLine(now);
while (DateTime.Now == DateTime.Now)
{
    DateTime nuw = DateTime.Now;
    sw.WriteLine(nuw);
    if (nuw == now)
    {

        sw.WriteLine("It worked");
    }             
}

我知道while循环是可怕的,但我只是看到有什么可行的。我认为导致这个问题的是DateTime.Now,不会每秒更新/更改,它在整个持续时间内保持不变。即使是控制台并无休止地写出来,它仍然是最初被称为的日期。

所以,是的,我知道该怎么办。

6 个答案:

答案 0 :(得分:2)

您应该使用每X分钟触发一次的计时器来完成您的任务。你的while循环将锁定程序的UI并占用大量的CPU。

答案 1 :(得分:1)

==上的比较DateTime比较内部滴答。刻度是100 ns或一千万分之一秒,在一毫秒内有10,000个刻度。相反,windows运行的周期时间约为20ms。比较就像试图在大小相当的大海捞针中找到针。

使用(nuw >= now)代替,比较完全匹配或现在之后。

答案 2 :(得分:1)

System.Threading.Timer类应该可以解决问题。您必须为System.Threading命名空间提供一个使用。

    static public void ListProcesses(Object stateInfo)
    {
        Process[] processlist = Process.GetProcesses();

        foreach (Process theprocess in processlist)
        {
            Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
        }
    }

    static void Main(string[] args)
    {
        //create a callback to our worker method
        TimerCallback callback = new TimerCallback(ListProcesses);

        // create a one minute timer tick
        Timer stateTimer = new Timer(callback, null, 0, 60000);

        // loop here forever
        while (true)
        {
            //sleep every second so we dont hog the cpu
            Thread.Sleep(1000);

            //add program control logic
            //if we want to exit the program with anything other than closing the window
        }
    }

答案 3 :(得分:0)

你应该尝试像

这样的东西
if(now.CompareTo(nuw) < 0)

答案 4 :(得分:0)

比较时间上的平等有点像试图在射箭中分裂箭头。准确一分钟就不太可能了。

我想你想要if (nuw >= now)

答案 5 :(得分:0)

从我的角度来看,你造成问题的最大问题是你的变量命名,除非我遗漏了一些东西 - 总是使用清晰的变量名,这样你的代码就会自然地读出来。

如上所示使用计时器肯定是解决问题的绝佳方法,但是我会继续并继续使用您编写的代码的主题,因为计时器答案的作者已经涵盖了一个很好。

我必须承认,对于“while(true)”循环也往往非常害羞,因为我宁愿通过Start()和Stop()方法以及_isRunning变量更加主动地控制停止应用程序 - _isRunning就是你的循环条件。为简单起见,我会坚持一段时间(真实)。

所以,稍微改写一下,你的循环看起来像这样:

DateTime timeOfNextOperation = DateTime.Now.AddMinutes(1);
Console.WriteLine(timeOfNextOperation);
while (true)
{
    if (DateTime.Now >= timeOfNextOperation)
    {
        Console.WriteLine("Do Stuff Here");
        timeOfNextOperation = DateTime.Now.AddMinutes(1);
    }
    Thread.Sleep(1000);
}

你绝对必须将某种收益(某种类型的睡眠)放入你的循环中,否则你将在紧密的循环中使用100%的cpu。即使是1分钟的睡眠也会产生很大的不同,但要想想你是否真的需要它才能快速旋转 - 在这种情况下,它肯定不会,你每分钟只旋转一次每一秒都足够了。

你的循环也没有重置它,以便通过设置下一个操作的时间来实现分钟,上面的操作。请注意,在这个例子中,我在完成任务后设置它(在这种情况下,打印一行:)) - 这意味着它将在每次执行之间运行1分钟,而不是每分钟 - 即任务需要30秒,然后它将在1分钟,然后2分30秒发生。如果你把任务放在AFTER之后它将安排在它开始运行1分钟后运行,所以它将在1分钟然后2分钟运行,危险的是如果你的任务需要超过1分钟,那么它将直接旋转回来试。

作为一般规则,永远不要仅仅与范围的结尾进行比较,总是与&lt; =或&gt; =进行比较 - 在​​某些情况下,它不是必需的(例如,如果你一次一个地循环一个循环你不可能错过最后一个)但是这是一个很好的习惯,所以你不能最终得到你没有意识到的情况可以跳过一个。< / p>

以上所说的我确实认为Timer是你最好的选择,我对infomaniac的优秀代码示例进行的唯一优化就是你不需要创建委托引用,它隐含在较新的版本中.NET。

Timer stateTimer = new Timer(ListProcesses, null, 0, 60000);

希望有所帮助。