【问题标题】:Call Thread.Sleep from the Task从任务中调用 Thread.Sleep
【发布时间】:2013-12-16 12:13:33
【问题描述】:

在任务中使用 Thread.Sleep() 是否正确。还是仅与任务一起使用计时器(.Net 4.5 及更高版本中的 Task.Delay() )?或者可能存在其他方法。

【问题讨论】:

  • 问题是你想达到什么目标?因为所有方法都有利有弊。
  • 您可以,但这是一个非常糟糕的做法,因为您正在禁用可用于服务其他 tash 的 ThreadPool 线程。你想达到什么目的?
  • @MattWilko 我认为 SerG 正在为 .NET 4.0 寻找 Task.Delay() 的替代品,因为它是在 .NET 4.5 中引入的。
  • 如果你在.Net4.0寻找Task.Delay
  • Serg,它适用于 .NET 4.0 吗?你也想要CancellationToken吗?

标签: .net c#-4.0 task-parallel-library delay thread-sleep


【解决方案1】:

可以在任务中使用Thread.Sleep。 但在大多数情况下,我更喜欢使用不会阻塞线程的await Task.Delay

如果你使用Task.Run(它使用一个线程池线程),那么你应该尽量不要阻塞线程。由于是共享线程,可能还有其他代码等待运行。

当我使用完线程后,我仍然会使用Thread.Sleep(0) 来让出处理器并放弃你的时间片。

【讨论】:

  • 确实,您可以使用它,但就 OP 而言,我会说当它可以处理时休眠一个任务池线程绝对是“不正确的”其他工作!
  • dcastro,您确定在编译器优化期间没有将 Sleep(0) 删除为无意义的冗余语句吗?我在 msdn 中没有找到任何关于这种技巧的信息。
  • @SerG From here: "指定零 (0) 表示应该暂停该线程以允许其他等待线程执行。"
【解决方案2】:

似乎真正的问题是如何在 .NET 4.0 中实现与 .NET 4.5 的 Task.Delay 相同的效果。

首先,如果您使用 Visual Studio 2012+,您可以将 Microsoft.Bcl.Async nuget 包添加到您的项目中,以启用 async/await 和其他新功能,例如 Task.Delay。这是最方便的方法。

如果您使用的是 Visual Studio 2010,则可以通过创建一个在计时器到期时完成的 TaskCompletionSource 来获得相同的结果。 ParallelExtensionsExtras 库已将其作为一组扩展方法提供。

基本函数是StartNewDelayed,还有很多便利重载:

    /// <summary>Creates a Task that will complete after the specified delay.</summary>
    /// <param name="factory">The TaskFactory.</param>
    /// <param name="millisecondsDelay">The delay after which the Task should transition to RanToCompletion.</param>
    /// <param name="cancellationToken">The cancellation token that can be used to cancel the timed task.</param>
    /// <returns>A Task that will be completed after the specified duration and that's cancelable with the specified token.</returns>
    public static Task StartNewDelayed(this TaskFactory factory, int millisecondsDelay, CancellationToken cancellationToken)
    {
        // Validate arguments
        if (factory == null) throw new ArgumentNullException("factory");
        if (millisecondsDelay < 0) throw new ArgumentOutOfRangeException("millisecondsDelay");

        // Check for a pre-canceled token
        if (cancellationToken.IsCancellationRequested)
            return factory.FromCancellation(cancellationToken);

        // Create the timed task
        var tcs = new TaskCompletionSource<object>(factory.CreationOptions);
        var ctr = default(CancellationTokenRegistration);

        // Create the timer but don't start it yet.  If we start it now,
        // it might fire before ctr has been set to the right registration.
        var timer = new Timer(self =>
        {
            // Clean up both the cancellation token and the timer, and try to transition to completed
            try
            {
                ctr.Dispose();
            }
            catch (NullReferenceException)
            {
                // Eat this. Mono throws a NullReferenceException when constructed with
                // default(CancellationTokenRegistration);
            }

            ((Timer)self).Dispose();
            tcs.TrySetResult(null);
        });

        // Register with the cancellation token.
        if (cancellationToken.CanBeCanceled)
        {
            // When cancellation occurs, cancel the timer and try to transition to canceled.
            // There could be a race, but it's benign.
            ctr = cancellationToken.Register(() =>
            {
                timer.Dispose();
                tcs.TrySetCanceled();
            });
        }

        // Start the timer and hand back the task...
        try { timer.Change(millisecondsDelay, Timeout.Infinite); }
        catch(ObjectDisposedException) {} // in case there's a race with cancellation; this is benign

        return tcs.Task;
    }

大部分代码处理正确处理计时器和处理取消。

【讨论】:

    【解决方案3】:

    在 .NET 4.5 中,您应该使用 Task.Delay。在 .NET 4.0 中,由于在 Task 中没有 Task.DelayThread.Sleep,这是一种不好的做法……创建自定义任务,并使用计时器将 ti 标记为已完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 2011-03-24
      相关资源
      最近更新 更多