我会使用生产者 - 消费者模式的简单变体.你有两个共享整数变量的theads,一个生产者和一个消费者.生产者System.Threading.Timer每秒都会触发一次,此时Interlocked.Increment变量会调用消费者.Interlocked.Decrement当计数器大于零时,消费者逻辑反复检查馈送和计数器.消费者逻辑将受到Monitor.TryEnter处理重新入侵的保护.这是示例代码.
public static FeedCheck{
int _count = 0;
static object _consumingSync = new object();
static Threading.Timer _produceTimer;
private static void Consume() {
if (!Monitor.TryEnter(_consumingSync)) return;
try {
while(_count > 0) {
// check feed
Interlocked.Decrement(ref _count);
}
}
finally { Monitor.Exit(_consumingSync); }
}
private static void Produce() {
Interlocked.Increment(ref _count);
Consume();
}
public static void Start() {
// small risk of race condition here, but not necessarily
// be bad if multiple Timers existed for a moment, since only
// the last one will survive.
if (_produceTimer == null) {
_produceTimer = new Threading.Timer(
_ => FeedCheck.Produce(), null, 0, 1000
);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
FeedCheck.Start();
Run Code Online (Sandbox Code Playgroud)
.NET Threading的一个很好的资源(除了MSDN Library的东西)是Jon Skeet的文档,其中包括"更多方法" 下的生产者 - 消费者的这个例子Monitor.
顺便说一句,真正的生产者 - 消费者模式围绕着一组工作数据,一个或多个线程通过向该集合添加数据来产生工作,而一个或多个其他线程消费者通过从该集合中移除数据来工作.在上面的变体中,"工作数据"仅仅是我们需要立即检查Feed的次数的计数.
(另一种方法,而不是定时器回调调用Consume,用于定时器回调锁定和脉冲Monitor消耗等待.在这种情况下,消耗有一个无限循环,就像while(true)你开始一次它自己的线程.所以没有必要支持re-entrancy与调用Monitor.TryEnter.)