Is it always bad to use Thread.Sleep()?
我为类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public static class RandomExtension { private static bool _isAlive; private static Task _executer; public static void ExecuteRandomAsync(this Random random, int min, int max, int minDuration, Action action) { Task outerTask = Task.Factory.StartNew(() => { _isAlive = true; _executer = Task.Factory.StartNew(() => { ExecuteRandom(min, max, action); }); Thread.Sleep(minDuration); StopExecuter(); }); } private static void StopExecuter() { _isAlive = false; _executer.Wait(); _executer.Dispose(); _executer = null; } private static void ExecuteRandom(int min, int max, Action action) { Random random = new Random(); while (_isAlive) { Thread.Sleep(random.Next(min, max)); action(); } } } |
它很好用。
但是在这个例子中使用
使用
因此,在这种情况下,您应该使用:
1 | await Task.Delay(minDuration); |
这不会挂起整个线程,而是只挂起要挂起的单个任务。同一线程上的所有其他任务都可以继续运行。
我使用
我认为你选择的设计还有其他问题。
相反,我会用另一种方式。同时保留已经创建的大多数内部构件,但将它们放在不同的类中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | public class ActionInvoker { private readonly Action _actionToInvoke; public ActionInvoker(Action actionToInvoke) { _actionToInvoke = actionToInvoke; _cancellationTokenSource = new CancellationTokenSource(); } private readonly CancellationTokenSource _cancellationTokenSource; private Task _executer; public void Start(int min, int max, int minDuration) { if (_executer != null) { return; } _executer = Task.Factory.StartNew( async () => await ExecuteRandomAsync(min, max, _actionToInvoke), _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default) .Unwrap(); } private void Stop() { try { _cancellationTokenSource.Cancel(); } catch (OperationCanceledException e) { // Log the cancellation. } } private async Task ExecuteRandomAsync(int min, int max, Action action) { Random random = new Random(); while (!_cancellationTokenSource.IsCancellationRequested) { await Task.Delay(random.Next(min, max), _cancellationTokenSource.Token); action(); } } } |
通过线程池,您可以使用线程的资源(F.E.RAM)来处理其他一些小任务。为了做到这一点,Windows允许您将线程置于一个特殊的可警报状态,以便它可以被唤醒并临时使用。
因此,
这样想。
休眠线程是危险的,因为通常不止一个任务依赖于该线程,更不用说程序的关键组件也可以。不要在线程上使用EDOCX1[1]是不合适的,当它们对您的程序有利时,您将希望使用它们。
由于不可预知的行为,很多人被教导不要睡线。这就像管理一个团队,最终你不得不让一些人去吃午饭,只要其余的人都能正常工作,而你选择去吃午饭的人都出去了,那么你就应该很好,还能继续工作。
如果项目中有人依赖他们的存在,就不要派人去吃午饭。
所有答案都是正确的,我想增加一个实用的观点:
当您有一个远程非实时组件要测试(例如,搜索引擎)时,您需要给它时间,以便在再次引用它进行断言之前进入它的新状态。换句话说,您希望将测试暂停一段时间。由于测试本身的性能是不相关的(请区分测试的性能和组件的性能),您有时更喜欢保持代码(测试的)尽可能简单和直接,并且避免了异步代码的最低复杂性。当然,您可以开始一个新的测试,而不是等待您的组件(这是