我的程序中有两个CRITERIA决定一个线程是等待还是继续。
第一条标准: 更改XML文件。我有一个文件观察器,如果XML文件发生变化,则设置AutoResetEvent
(_waitTillXmlChanges.Set()
),因此线程应该继续。
第二个标准: 到期日已到。如果今天是文件传输应该发生的日期,则第二个标准已经满足,因此线程应该继续。
我当前的代码:
var waitTillNextWakeUpDay = NextWakeUpDay - DateTime.Now;
//SPURIOS WAKE-UP calls happening here
_waitTillXmlChanges.WaitOne(waitTillNextWakeUpDay);
我理解为了避免虚假的唤醒调用,while-loop
附近放置WaitOne()
,以便线程在错误唤醒的情况下再次进入等待模式。
问题:我不明白我应该如何实现围绕WaitOne()
的故障安全while循环(这取决于两个条件)。
重要提示:由于每当XML文件发生变化时我都会在日志文件上打印,我可以说伪造的唤醒呼叫不是因为FileWatcher。最有可能的是,问题出在_waitTillXmlChanges.WaitOne(waitTillNextWakeUpDay)
行,它不能等待waitTillNextWakeUpDay
的时间跨度(大约1天)并且每15-30分钟就会清醒一次。
上面的代码在我的电脑上正常工作,但虚假唤醒的问题正在另一台PC上出现。
答案 0 :(得分:0)
WaitHandle.WaitOne(TimeSpan timeout)
的官方文档有一个奇怪的界限:
超时的最大值为
Int32.MaxValue
(2147483647)。
不确定这究竟是什么意思,但是 TimeSpan.FromTicks(int.MaxValue)
等于大约3分半钟,所以可能,这个方法不是'打算用于如此长时间的跨度。
WaitOne
方法会返回bool
,您需要检查一下,因为它可以在返回之前获得信号,因此您可以在循环中使用它,使用SpinWait
struct或直接Thread.Yield()
方法:
var waitTillNextWakeUpDay = NextWakeUpDay - DateTime.Now;
var spin = new SpinWait();
while (!eventToWait.WaitOne(waitTillNextWakeUpDay))
{
// will define, which method to call:
// Thread.Sleep(0), Thread.Sleep(1), or Thread.Yield()
// based on number of spins
spin.SpinOnce();
// simply yield execution to other thread
// Thread.Yield();
}
在此循环之后,您可以检查旋转的Count
属性,以便获得唤醒次数。
旁注:您是否尝试远程调试服务?如果它在15-30分钟内唤醒,您可以通过远程调试器连接到它,并在代码中插入breakpoint,这可以帮助您定义问题的原因:
using System.Diagnostics;
Debugger.Break();