如果超时后任务仍未完成,Task.Wait(int) 是否会停止任务?

发布于 2024-09-29 14:19:56 字数 300 浏览 3 评论 0 原文

我有一个任务,我预计它需要不到一秒钟的时间才能运行,但如果它需要的时间超过几秒钟,我想取消该任务。

例如:

Task t = new Task(() =>
        {
            while (true)
            {
                Thread.Sleep(500);
            }
        });
t.Start();
t.Wait(3000);

请注意,3000 毫秒后等待到期。超时后任务是被取消还是任务仍在运行?

I have a task and I expect it to take under a second to run but if it takes longer than a few seconds I want to cancel the task.

For example:

Task t = new Task(() =>
        {
            while (true)
            {
                Thread.Sleep(500);
            }
        });
t.Start();
t.Wait(3000);

Notice that after 3000 milliseconds the wait expires. Was the task canceled when the timeout expired or is the task still running?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

╰ゝ天使的微笑 2024-10-06 14:19:56

Task.Wait() 等待指定时间段内的任务完成,并返回任务是否在指定时间(或更早)内完成。任务本身不会被修改,也不依赖于等待。

阅读精彩系列: . NET.NET 中的并行性 – 第 10 部分,PLINQ 中的取消和 Parallel 类 作者:Reed Copsey

以及: 并行编程:任务取消

检查以下代码:

var cts = new CancellationTokenSource();

var newTask = Task.Factory.StartNew(state =>
                           {
                              var token = (CancellationToken)state;
                              while (!token.IsCancellationRequested)
                              {
                              }
                              token.ThrowIfCancellationRequested();
                           }, cts.Token, cts.Token);


if (!newTask.Wait(3000, cts.Token)) cts.Cancel();

Task.Wait() waits up to specified period for task completion and returns whether the task completed in the specified amount of time (or earlier) or not. The task itself is not modified and does not rely on waiting.

Read nice series: Parallelism in .NET, Parallelism in .NET – Part 10, Cancellation in PLINQ and the Parallel class by Reed Copsey

And: .NET 4 Cancellation Framework / Parallel Programming: Task Cancellation

Check following code:

var cts = new CancellationTokenSource();

var newTask = Task.Factory.StartNew(state =>
                           {
                              var token = (CancellationToken)state;
                              while (!token.IsCancellationRequested)
                              {
                              }
                              token.ThrowIfCancellationRequested();
                           }, cts.Token, cts.Token);


if (!newTask.Wait(3000, cts.Token)) cts.Cancel();
梦旅人picnic 2024-10-06 14:19:56

如果您想取消Task,则应在创建任务时传入CancellationToken。这将允许您从外部取消Task。如果需要,您可以将取消与计时器联系起来。

要使用取消令牌创建任务,请参阅以下示例:

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;

var t = Task.Factory.StartNew(() => {
    // do some work
    if (token.IsCancellationRequested) {
        // Clean up as needed here ....
    }
    token.ThrowIfCancellationRequested();
}, token);

要取消 Task,请在 tokenSource 上调用 Cancel()

If you want to cancel a Task, you should pass in a CancellationToken when you create the task. That will allow you to cancel the Task from the outside. You could tie cancellation to a timer if you want.

To create a Task with a Cancellation token see this example:

var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;

var t = Task.Factory.StartNew(() => {
    // do some work
    if (token.IsCancellationRequested) {
        // Clean up as needed here ....
    }
    token.ThrowIfCancellationRequested();
}, token);

To cancel the Task call Cancel() on the tokenSource.

小耗子 2024-10-06 14:19:56

该任务仍在运行,直到您明确告诉它停止或循环完成(这永远不会发生)。

您可以检查 Wait 的返回值来查看此内容:(

来自 http://msdn .microsoft.com/en-us/library/dd235606.aspx
返回值

类型:System.Boolean
如果任务在指定时间内完成执行,则为 true;否则为假。

The task is still running until you explicitly tell it to stop or your loop finishes (which will never happen).

You can check the return value of Wait to see this:

(from http://msdn.microsoft.com/en-us/library/dd235606.aspx)
Return Value

Type: System.Boolean
true if the Task completed execution within the allotted time; otherwise, false.

﹏半生如梦愿梦如真 2024-10-06 14:19:56

超时后任务是否被取消或者任务仍在运行?

否和是。

传递给 Task.Wait 的超时是针对 Wait 的,而不是针对任务的。

Was the task canceled when the timeout expired or is the task still running?

No and Yes.

The timeout passed to Task.Wait is for the Wait, not the task.

☆獨立☆ 2024-10-06 14:19:56

如果您的任务调用任何同步方法来执行任何类型的 I/O 或其他需要时间的未指定操作,则没有通用方法可以“取消”它。

根据您尝试“取消”它的方式,可能会发生以下情况之一:

  • 操作实际上被取消,并且它所处理的资源处于稳定状态(您很幸运!)
  • 操作实际上被取消,并且它所处理的资源 处于稳定状态on 处于不一致状态(稍后可能会导致各种问题)
  • 操作继续进行,并且可能会干扰其他代码正在执行的操作(稍后可能会导致各种问题)
  • 操作失败或导致进程崩溃。
  • 您不知道会发生什么,因为它没有记录

在有效的场景中,您可以并且可能应该使用其他答案中描述的通用方法之一取消任务。但是,如果您在这里是因为想要中断特定的同步方法,最好查看该方法的文档,以了解是否有办法中断它,它是否有“超时”参数,或者是否存在可中断的变化它的。

If your task calls any synchronous method that does any kind of I/O or other unspecified action that takes time, then there is no general way to "cancel" it.

Depending on how you try to "cancel" it, one of the following may happen:

  • The operation actually gets canceled and the resource it works on is in a stable state (You were lucky!)
  • The operation actually gets canceled and the resource it works on is in an inconsistent state (potentially causing all sorts of problems later)
  • The operation continues and potentially interferes with whatever your other code is doing (potentially causing all sorts of problems later)
  • The operation fails or causes your process to crash.
  • You don't know what happens, because it is undocumented

There are valid scenarios where you can and probably should cancel a task using one of the generic methods described in the other answers. But if you are here because you want to interrupt a specific synchronous method, better see the documentation of that method to find out if there is a way to interrupt it, if it has a "timeout" parameter, or if there is an interruptible variation of it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文