【问题标题】:Check if a task is waiting or busy检查任务是否正在等待或忙碌
【发布时间】:2018-07-27 12:07:58
【问题描述】:

给定一个任务列表,我如何检查所有这些任务当前是否正在等待或忙于计算?

“等待”是指任务不会继续,直到其他情况发生变化:任务卡在await otherTaskawait semaphore.AsyncWaitHandle() 等。

这是给discrete event simulation

下面是我正在尝试做的一个示例:我想模拟一些共享资源并需要一些时间才能完成的工作(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


【解决方案1】:

您可以使用 await 等待任务完成后再开始下一个任务。

public async void starttasks()
    {
        await Task.Run(() => {  /* your code */  } );  //Task1
        await Task.Run(() => {  /* your code */  } );  //Task2
        await Task.Run(() => {  /* your code */  } );  //Task3
        await Task.Run(() => {  /* your code */  } );  //Task4 
        await Task.Run(() => {  /* your code */  } );  //Task5
    }

这将执行第一个任务并等待它完成分别执行下一个任务。 希望对你有帮助。

您也可以在我上面提供的代码之后添加task.delay,等待所有任务完成。

await Task.Delay(5000);

【讨论】:

  • 我知道如何等到某些任务完成(async Task.WhenAll()Task.WaitAll(),但我只想等到所有任务都阻塞(主动消耗处理器时间)
猜你喜欢
  • 2014-04-07
  • 1970-01-01
  • 2010-11-09
  • 2015-03-17
  • 2012-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-15
相关资源
最近更新 更多