线程定期调用不带线程池的方法

本文关键字:线程 方法 调用 | 更新日期: 2023-09-27 18:25:05

我想要一个每500毫秒执行一个方法的线程。但是,我希望这种情况发生在单个线程上——我不希望它在线程池上运行。因此,System.Timer和System.Threading.Timer是不可能的。有标准的方法吗?

线程定期调用不带线程池的方法

您可以执行这样的循环:

var sw = Stopwatch.StartNew();
while (youStillWantToProcess)
{
    DoYourStuff();
    while (sw.Elapsed < TimeSpan.FromMilliseconds(500))
        Thread.Yield(); // Or Thread.Sleep(10) for instance if you can afford some inaccuracy
    sw.Restart();
}

Thread.Yield调用将告诉操作系统暂时在CPU上调度不同的线程。不过,您的线程将保留在活动线程列表中,以便能够快速恢复处理。

类似的,可能更好的方法是:

var sw = Stopwatch.StartNew();
var spinWait = new SpinWait();
while (youStillWantToProcess)
{
    DoYourStuff();
    spinWait.Reset();
    while(sw.Elapsed < TimeSpan.FromMilliseconds(500))
        spinWait.SpinOnce();
    sw.Restart();
}

看看SpinWait结构。它实现了一个不同的逻辑:它将在短时间内非常激进,过一小段时间后,它将开始Yield,然后是Sleep(0),最后是Sleep(1):

来自源代码:

// These constants determine the frequency of yields versus spinning. The
// numbers may seem fairly arbitrary, but were derived with at least some 
// thought in the design document.  I fully expect they will need to change 
// over time as we gain more experience with performance.
internal const int YIELD_THRESHOLD = 10; // When to switch over to a true yield. 
internal const int SLEEP_0_EVERY_HOW_MANY_TIMES = 5; // After how many yields should we Sleep(0)?
internal const int SLEEP_1_EVERY_HOW_MANY_TIMES = 20; // After how many yields should we Sleep(1)?

你要求准确度,所以这里有了,但老实说,使用500毫秒的旋转等待时间感觉有点奇怪…