1

我的程序中有两个 CRITERIA 决定线程应该等待还是继续。

第一个标准: XML 文件中的更改。我有一个文件观察器,如果 XML 文件发生更改,它会设置一个AutoResetEvent(_waitTillXmlChanges.Set()),因此线程应该继续。

第二个标准:到期日已到。如果今天是应该进行文件传输的日期,那么第二个标准已经满足,因此线程应该继续。

我当前的代码:

var waitTillNextWakeUpDay = NextWakeUpDay - DateTime.Now;
//SPURIOS WAKE-UP calls happening here
_waitTillXmlChanges.WaitOne(waitTillNextWakeUpDay);

我知道,为了避免虚假的唤醒调用,将 awhile-loop放在 a 周围,WaitOne()以便线程在错误唤醒时再次进入等待模式。

问题:我不明白我应该如何实现故障安全while循环WaitOne()(这取决于两个条件)。

重要线索:因为每当 XML 文件发生更改时我都会在日志文件上打印,所以我可以说虚假的唤醒呼叫不是因为 FileWatcher。最有可能的是,问题出在 line 上_waitTillXmlChanges.WaitOne(waitTillNextWakeUpDay),它无法等待waitTillNextWakeUpDay(大约 1 天)的时间跨度,并且每 15-30 分钟就会醒来。

上面的代码在我的 PC 上可以正常工作,但在另一台 PC 上出现了虚假唤醒的问题。

4

1 回答 1

0

官方文档WaitHandle.WaitOne(TimeSpan timeout)有一条奇怪的线:

超时的最大值为( Int32.MaxValue2147483647)。

不知道这到底是什么意思,但TimeSpan.FromTicks(int.MaxValue)等于大约 3 分半钟,所以,也许,这种方法不适合这么长时间的使用。

WaitOne方法返回 a bool,您需要检查它,因为它可以在收到信号之前返回,因此您可以在循环中使用它,使用SpinWaitstruct或使用直接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 分钟内唤醒,您可以通过远程调试器连接到它,并通过在代码中插入断点来命中断点,这可以帮助您定义问题的原因:

using System.Diagnostics;

Debugger.Break();
于 2017-04-13T14:43:00.653 回答