C# 使所有线程都睡眠

C# 使所有线程都睡眠,c#,multithreading,C#,Multithreading,我使用新的并行程序。为此,我创建了多个线程来执行相同的操作 如果其中一个线程失败,这意味着我工作“太快”,我需要让所有线程休息几秒钟 有没有一种方法可以执行类似于Thread.Sleep的操作-只需在所有线程上同时执行相同的操作?这是对问题的直接回答,除了Parallel.for位。 这确实是一种可怕的模式;您可能应该使用适当的同步机制,让工作线程在没有抢占的情况下偶尔检查它们是否需要“退出” 此外,这使用了Thread.Suspend和Thread.Resume,它们都是不推荐使用的,并且有很

我使用新的并行程序。为此,我创建了多个线程来执行相同的操作

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


有没有一种方法可以执行类似于Thread.Sleep的操作-只需在所有线程上同时执行相同的操作?

这是对问题的直接回答,除了
Parallel.for
位。 这确实是一种可怕的模式;您可能应该使用适当的同步机制,让工作线程在没有抢占的情况下偶尔检查它们是否需要“退出” 此外,这使用了
Thread.Suspend
Thread.Resume
,它们都是不推荐使用的,并且有很好的理由(从):

“不要使用Suspend和Resume方法来同步线程的活动。挂起线程时,无法知道线程正在执行什么代码。如果在安全权限评估期间挂起一个线程,而该线程持有锁,则AppDomain中的其他线程可能会被阻止。如果在线程执行类构造函数时挂起该线程,则AppDomain中尝试使用该类的其他线程将被阻止。死锁很容易发生。”

(未经测试)

公共类工作者
{
私有只读线程[]\u线程;
私有只读对象_locker=新对象();
私有只读时间跨度_toFastSuspensionspan;
私有日期时间_lastSuspensionTime;
公共工作者(int numThreads,TimeSpan到FastSuspensionSpan)
{
_tooFastSuspensionSpan=tooFastSuspensionSpan;
_线程=可枚举。重复(新线程开始(DoWork),numThreads)
.选择(ts=>新线程(ts))
.ToArray();
}
公开募捐
{
foreach(var线程在_线程中)
{
thread.Start();
}
}
私房
{
而(!IsWorkComplete())
{
尝试
{
//你在这里工作吗
}
捕获(TooFastException)
{
SuspendAll();
}
}
}
私有void SuspendAll()
{
锁(储物柜)
{
//我们不希望N个几乎同时发生的故障导致睡眠持续时间为N*\u tooFastSuspensionSpan
//1秒是任意的。我们不能确定它,因为我们强制挂起线程
var now=DateTime.now;
如果(现在)从秒(1)中减去(\u lastSuspensionTime)<\u tooFastSuspensionSpan+TimeSpan.)
返回;
_lastSuspensionTime=现在;
var otherThreads=_threads.Where(t=>t.ManagedThreadId!=Thread.CurrentThread.ManagedThreadId).ToArray();
foreach(其他线程中的var otherThread)
otherThread.Suspend();
线程。睡眠(_tooFastSuspensionSpan);
foreach(其他线程中的var otherThread)
otherThread.Resume();
}
}
}

您需要创建工作线程的资源清册,然后也许可以使用Thread.Suspend和Resume方法。请注意,使用Suspend可能很危险(例如,线程可能在挂起之前已获得锁)。和suspend/resume由于这些问题已被标记为obsole。

如果您在所有线程上睡眠,您等待的线程不是没有完成吗?您至少需要一个正在运行的线程。不,线程在我的电脑上执行需要电脑“冷静”的操作。第一个线程将在几秒钟后重试。(希望您理解)不需要运行线程。最后,线程会写他失败了——我只是不想让所有线程都写失败,而是从原始线程的错误中吸取教训,然后等待。(天哪……这是一个笨拙的解释)您可以在每个操作结束时检查一个变量,并让任何线程根据当前值的大小进行睡眠。这有意义吗?有点,但这是一个非常难看的代码。我需要在每次操作后检查该变量,看看是否需要睡眠。我宁愿在所有线程上写日志失败,让它们都进入睡眠状态。”这意味着我的工作“太快了”-这应该会敲响警钟。听起来你要么有同步问题,要么你正在并行一些本来就不可并行的东西…我理解你的解决方案。这很有意义。谢谢。
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();
        }
    }

}