【问题标题】:Synchronously run a task in the same thread (no threadpool) with a timeout在同一个线程(无线程池)中同步运行任务并超时
【发布时间】:2013-04-12 06:35:30
【问题描述】:

我想使用 Task 类型,但不是使用 TPL,而是使用 .NET4.5/C#async。

问题是,我对我的案子有一些要求:

  • 我希望任务同步运行(有人推荐RunSynchronously(),有人推荐Wait(),还有人推荐ContinueWith(_, TaskContinuationOptions.ExecuteSynchronously),这里哪一个合适?)。
  • 我希望任务在同一个线程中运行(所以,根本不使用线程池)。
  • 我希望任务在某个超时过后停止,并抛出异常。

对于后者,我想我需要Task.Delay(),但我不确定如何将它与前两个要求结合起来。 谢谢

【问题讨论】:

  • Task 是任务并行库 (TPL) 的一部分,它确实在幕后使用了 ThreadPool,这意味着它由 TaskSchedule 安排,最终将在不同的平台上运行线程。
  • 不,有办法通过使用适当的调度程序 AFAIU 使其不使用线程池
  • 使用Task 对象的全部意义在于执行异步操作,正如类本身的文档所表明的那样。
  • 我知道重点是什么,我只是想做点不一样的事情
  • 我不明白你为什么要在这里使用Task。接受超时参数的普通方法不适合您吗?

标签: c# task-parallel-library async-await c#-5.0 continuations


【解决方案1】:

此答案基于@svick 的评论。

我将假设您希望该方法的所有“工作”与调用者在同一个线程上完成,但您不介意线程池线程是否用于取消目的(我假设这是因为您提到了Task.Delay,它将使用Timer,当计时器触发时,它将使用线程池线程。

也就是说,不需要Task,因为当方法返回时,您会确定任务已完成。只需一个带有超时的常规方法即可:

static void DoSomethingOrThrowAfterTimeout(int millisecondsTimeout)
{
    CancellationTokenSource cts = new CancellationTokenSource(millisecondsTimeout);
    CancellationToken ct = cts.Token;
    // do some work
    ct.ThrowIfCancellationRequested();
    // do more work
    ct.ThrowIfCancellationRequested();
    // repeat until done.
}

显然,通过这种使用协作取消的方法,该方法不会在超时时准确超时,因为它取决于您可以在方法中拆分工作的程度。

如果您想避免使用另一个线程(对于CancellationTokenSource),那么您可以跟踪开始时间,然后在各个点检查已经过去了多少时间(看看您是否超过了超时时间)在方法中(就像上面如何使用ct.ThrowIfCancellationRequested()

【讨论】:

  • @knocte,在这种情况下,您不能像上面那样使用Task.Delay 或我的CancellationTokenSource 方法,而是必须将方法的开始时间与当前时间进行比较,也许使用Environment.TickCountmsdn.microsoft.com/en-us/library/…
猜你喜欢
  • 1970-01-01
  • 2021-04-18
  • 2012-09-03
  • 2015-07-13
  • 2021-04-11
  • 1970-01-01
  • 2021-04-28
  • 2016-06-14
  • 1970-01-01
相关资源
最近更新 更多