线程周期性调用没有线程池的方法

时间:2014-09-30 23:32:14

标签: c# multithreading

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

1 个答案:

答案 0 :(得分:4)

你可以这样做一个循环:

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毫秒的时间感觉有些奇怪......