【发布时间】:2018-07-27 12:07:58
【问题描述】:
给定一个任务列表,我如何检查所有这些任务当前是否正在等待或忙于计算?
“等待”是指任务不会继续,直到其他情况发生变化:任务卡在await otherTask 或await semaphore.AsyncWaitHandle() 等。
下面是我正在尝试做的一个示例:我想模拟一些共享资源并需要一些时间才能完成的工作(t1、t2、t3)。
所以 t1 和 t2 共享资源,不能同时运行。 t3 要求 t1 是完整的。
在现实世界中,这些任务需要几个小时,我可以简单地使用 Task.Delay() 来模拟,但我不想等那么久。
所以每当所有任务被阻塞时,我想快进时间。
所以我需要Task.Delay()以外的东西,如果所有任务都被阻塞,就释放一个任务。
public static async Task MainAsync()
{
Task t1 = Screw1(), t2=Screw2(), t3 = ThightenBolts1(t1);
await Task.WhenAll(t1,t2,t3); // this takes 6 hours :(
}
// There is only one screwdriver for everyone
static SemaphoreSlim screwdriver = new SemaphoreSlim(1,1);
static async Task Screw1()
{
await screwdriver.WaitAsync();
await Task.Delay(TimeSpan.FromHours(1));
Console.WriteLine("Item 1 screwed.");
screwdriver.Release();
}
static async Task Screw2()
{
await screwdriver.WaitAsync();
await Task.Delay(TimeSpan.FromHours(2));
Console.WriteLine("Item 2 screwed.");
screwdriver.Release();
}
static async Task ThightenBolts1(Task prevTask)
{
await prevTask;
await Task.Delay(TimeSpan.FromHours(3));
Console.WriteLine("Item 1 thightened.");
}
此模拟需要 6 小时才能完成。大多数时候,所有任务都被阻塞,等待模拟时间过去。
所以我想快进,但前提是当前没有任务正在运行一些计算。
为此,我需要检测到所有任务都在等待某事,而不是忙于计算。然后我可以实现 Task.Delay() 的一个版本,它继续前面的下一个任务。
【问题讨论】:
-
任务使用什么机制来阻塞?
-
不,没有标准的方法来做到这一点。例如,您必须查看超时或异常取消。
-
你们俩都不应该使用任务构造函数永远,也不应该创建在线程池上运行代码的线程,只是让它们坐在那里无所事事完成一些操作。异步完成工作。让他们异步等待各种其他操作完成,这样他们就不会在持续时间内不必要地阻塞线程池线程。
-
@servy 我想让这个例子尽可能简单。使用 async / await 可以使用相同的代码,并且不使用线程,但仍然存在相同的问题:我想检测所有任务何时无法继续,直到过了一段时间,然后快进。目标是模拟真实世界的过程。任务本身永远不会做任何有意义的工作;目标是找出实际过程需要多长时间。
-
@servy 我根据您的建议使用异步重写了示例,希望现在我的意图更清楚了。基本问题仍然存在。
标签: c# synchronization task simulation blocking