我有一个程序可以处理并行运行的各种任务。单个任务充当各种管理器,确保在运行下一个任务之前满足某些条件。但是,我发现有时某个任务会长时间处于 WaitingToRun 状态。这是以下代码:
mIsDisposed = false;
mTasks = new BlockingCollection<TaskWrapper>(new ConcurrentQueue<TaskWrapper>());
Task.Factory.StartNew(() => {
while (!mIsDisposed) {
var tTask = mTasks.Take();
tTask.task.Start();
while (tTask.task.Status == TaskStatus.WaitingToRun) {
Console.WriteLine("Waiting to run... {0}", tTask.task.Id);
Thread.Sleep(200);
}
tTask.ready.Wait();
}
mTasks.Dispose();
});
DoWork();
DoWork();
DoWork();
DoWork();
DoWorkAsync();
DoWorkAsync();
DoWorkAsync();
DoWorkAsync();
DoWorkAsync();
DoWork();
TaskWrapper 非常简单地定义为:
private class TaskWrapper
{
public Task task { get; set; }
public Task ready { get; set; }
}
目前仅在 2 个地方添加了任务:
public void DoWork()
{
DoWorkAsync().Wait();
}
public Task DoWorkAsync()
{
ManualResetEvent next = new ManualResetEvent(false);
Task task = new Task(() => ActualWork(next));
Task ready = Task.Factory.StartNew(() => next.Wait());
mTasks.Add(new TaskWrapper() {
task = task,
ready = ready
});
return task;
}
哪里ActualWork(next)
来电next.Set()
。
在允许下一个工作项继续之前,这会将工作排队并等待直到next
已设置。您可以等待整个任务完成,然后通过调用DoWork()
或一次排队多个任务(应该在next
设置后运行)继续。
然而,当通过添加任务时DoWorkAsync()
,在调用之后tTask.task.Start()
,tTask.task
会处于 WaitingToRun 状态很长一段时间(如 30 秒到一分钟),然后神奇地开始运行。我已经使用 while 循环对此进行了监控,并且Waiting To Run... #
会显示相当长的一段时间。
呼叫DoWork()
总是立即运行。我确信这与调用Wait
设置为运行的任务有关。
我很茫然,在这里。
更新:
我已经设法使代码工作,但我仍然想知道为什么首先会出现问题。
经过一些实验性的更改,我设法解决了自己的问题,但这更像是“哦,所以我不能那样做”,而不是一个好的解决方案。事实证明,我的问题是让任务排队运行太快。通过修改DoWorkAsync()
为不再使用Task.Factory.StartNew
并更改tTask.ready.Wait()
为tTask.ready.RunSynchronously
我已经设法解决了我的问题。
TaskScheduler
延迟我的任务安排是否有原因?我是否饱和了一些基础资源?这里发生了什么?