在任务中使用Thread.Sleep()是否正确。或者只是一个与任务一起使用的计时器(.Net 4.5和后者中的Task.Delay())?或者可能存在其他方法。
答案 0 :(得分:5)
你可以在任务中使用Thread.Sleep
。
但在大多数情况下,我更喜欢使用await Task.Delay
来阻止线程。
如果您正在使用Task.Run
(使用ThreadPool线程),那么您应该尽量不阻止该线程。因为它是一个共享线程,所以可能还有其他代码在等待运行。
当我使用线程时,我仍然会使用Thread.Sleep(0)
来产生处理器并放弃你的时间片。
答案 1 :(得分: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;
}
大多数代码处理正确处理计时器和处理取消。
答案 2 :(得分:0)
在.NET 4.5中,您应该使用Task.Delay
。在.NET 4.0中,因为在Task中没有Task.Delay
和Thread.Sleep
是一种不好的做法...创建一个自定义任务,并使用一个计时器将ti标记为已完成。