代码之家  ›  专栏  ›  技术社区  ›  Faruz

使所有线程休眠

  •  2
  • Faruz  · 技术社区  · 15 年前

    我和新同事一起工作平行。用于它创建多个线程来执行相同的操作。

    如果其中一个线程失败,这意味着我工作“太快了”,我需要让所有线程休息几秒钟。

    有没有一种方法可以像线程。睡眠-只在所有线程上同时执行相同的操作?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Ani    15 年前

    这是对问题的直接回答,除了 Parallel.For 钻头。 这真是一个可怕的模式;您可能应该使用适当的同步机制,让工作线程在没有抢占的情况下偶尔检查它们是否需要“后退” 此外,它还使用 Thread.Suspend Thread.Resume 这两个都是不赞成的,而且有充分的理由(从 Thread.Suspend ):

    (未经测试)

    public class Worker
    {
        private readonly Thread[] _threads;
        private readonly object _locker = new object();
        private readonly TimeSpan _tooFastSuspensionSpan;
        private DateTime _lastSuspensionTime;
    
        public Worker(int numThreads, TimeSpan tooFastSuspensionSpan)
        {
            _tooFastSuspensionSpan = tooFastSuspensionSpan;
            _threads = Enumerable.Repeat(new ThreadStart(DoWork), numThreads)
                                 .Select(ts => new Thread(ts))
                                 .ToArray();
        }
    
        public void Run()
        {
            foreach (var thread in _threads)
            {
                thread.Start();
            }
        }
    
        private void DoWork()
        {
            while (!IsWorkComplete())
            {
                try
                {
                    // Do work here
    
                }
                catch (TooFastException)
                {
                    SuspendAll();
                }
            }
    
        }
    
        private void SuspendAll()
        {
            lock (_locker)
            {
                // We don't want N near-simultaneous failures causing a sleep-duration of N * _tooFastSuspensionSpan
                // 1 second is arbitrary. We can't be deterministic about it since we are forcefully suspending threads
                var now = DateTime.Now;
                if (now.Subtract(_lastSuspensionTime) < _tooFastSuspensionSpan + TimeSpan.FromSeconds(1))
                    return;
    
                _lastSuspensionTime = now;
    
                var otherThreads = _threads.Where(t => t.ManagedThreadId != Thread.CurrentThread.ManagedThreadId).ToArray();
    
                foreach (var otherThread in otherThreads)
                    otherThread.Suspend();
    
                Thread.Sleep(_tooFastSuspensionSpan);
    
                foreach (var otherThread in otherThreads)
                    otherThread.Resume();
            }
        }
    
    }
    
        2
  •  0
  •   VinayC    15 年前