我的应用程序中有一个事件会改变对象的状态,并在10秒后将该状态指定为重置状态。但是如果该事件在那10秒内再次触发,则事件不会改变状态,只是将计时器重置为零。
为了简洁易懂,以下是我的代码
目前我正在使用' ConcurrentQueue'在线程中被操纵
public class ToDo
{
public DateTime Expires { get; set; }
public Action StuffToDo { get; set; }
}
然后我的线程
public void MyWorkerThread(object parameters)
{
while (!<check if cancellation requested>)
{
ToDo stuff;
if (myConcurrentQueue.TryDequeue(out stuff))
{
if (DateTime.Now > stuff.Expires)
{
Task.StuffToDo.Invoke();
}
else
{
// queue it back if it is not time to execute it
//
myConcurrentQueue.Enqueue(stuff);
}
}
}
}
这是我的任务排队的事件处理程序
private ConcurrentDictionary<ToDo> _todoDictionary = new ConcurrentDictionary<ToDo>();
private ConcurrentQueue<ToDo> myConcurrentQueue = new ConcurrentQueue<ToDo>();
public void MyEventFired(MyEventArgs e)
{
ToDo todo = null;
if (_todoDictionary.ContainsKey(e.TaskType))
{
_todoDictionary.TryRemove(out todo);
if (DateTime.Now >= task.Expires)
{
todo = new ToDo();
todo.StuffToDo = new Action(() => { /* stuff here */ });
}
}
else
{
todo = new ToDo();
todo.StuffToDo = new Action(() => { /* stuff here */ });
}
todo.Expires = DateTime.Now + TimeSpan.FromSeconds(10.0);
_todoDictionary.Add(e.TaskType, todo);
myConcurrentQueue.Enqueue(todo);
}
有人告诉我,我可以使用TPL完成上述所有操作,而且我不需要工作线程,我可以使用&#39; Task.Delay&#39;。我还在考虑如何处理它。任何想法将不胜感激。
这就是我想要做的事情 我希望用Task.Run和/或Task.Delay()重写工作线程。继续使用序列。
答案 0 :(得分:1)
您当前的root
代码是一个忙碌的旋转循环。它在CPU核心上驱动到100%。你应该听到你的CPU风扇因此而旋转。
以下是我实现可重置延迟的方法:
MyWorkerThread
volatile int targetTicks = Environment.TickCount + (10 * 1000);
async Task WaitUntilTargetReachedAsync() {
while (true) {
var currentTicks = Environment.TickCount; //stabilize value
var targetTicksLocal = targetTicks; //volatile read, stabilize value
if (currentTicks >= targetTicksLocal) break; //Target reached.
await Task.Delay(TimeSpan.FromMilliseconds(targetTicksLocal - currentTicks));
}
}
将在到达WaitUntilTimeoutAsync()
时完成。您可以随时为targetTicks
添加时间,并targetTicks
进行调整。这样您就可以将计时器重置为现在加10秒:
WaitUntilTimeoutAsync()
现在您的任务完全在您需要的时候完成,您可以根据以下内容进行操作:
targetTicks = Environment.TickCount + (10 * 1000);