Imi*_*ew2 3 c# concurrency task
我有一个程序可以处理并行运行的各种任务。单个任务充当各种管理者,确保在运行下一个任务之前满足某些条件。但是,我发现有时任务会长时间处于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();
Run Code Online (Sandbox Code Playgroud)
TaskWrapper非常简单地定义为:
private class TaskWrapper
{
public Task task { get; set; }
public Task ready { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
目前仅在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;
}
Run Code Online (Sandbox Code Playgroud)
在哪里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延迟我的任务计划的原因?我是否饱和了一些基础资源?这里发生了什么?
线程将在系统的线程池中运行。线程池始终具有最小数量的可用线程(请参阅ThreadPool.SetMinThreads())。如果您尝试创建的线程数量超过了该数量,则在每个新线程启动之间会引入大约500毫秒的延迟。
线程池中也有最大线程数(请参阅ThreadPool.GetMaxThreads()),如果达到该限制,将不会创建新线程。它会等到旧线程死掉再安排新线程(或者,当然是重新安排旧线程以运行新线程)。
不过,您不太可能达到该限制-可能超过1000。
| 归档时间: |
|
| 查看次数: |
4194 次 |
| 最近记录: |