我使用新的Parallel.For创建多个线程来执行相同的操作。
如果其中一个线程失败,则表示我工作“太快”,我需要让所有线程休息几秒钟。
有没有办法执行类似Thread.Sleep的东西 - 只能在所有线程上同时执行相同操作?
答案 0 :(得分:2)
除了Parallel.For
位之外,这是问题的直接答案。
这真是一个可怕的模式;你可能应该使用正确的同步机制,让工作线程在没有抢占的情况下偶尔检查是否需要“退回”。
此外,这会使用Thread.Suspend
和Thread.Resume
这两个都已弃用,且有充分理由(来自Thread.Suspend):
“不要使用Suspend和Resume方法来同步线程的活动。当你挂起它时,你无法知道线程正在执行什么代码。如果你在安全权限评估期间持有锁时挂起一个线程,AppDomain中的其他线程可能会被阻塞。如果在执行类构造函数时挂起一个线程,AppDomain中尝试使用该类的其他线程将被阻止。死锁很容易发生。“
(未测试的)
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();
}
}
}
答案 1 :(得分:0)
您需要创建工作线程的清单,然后您可以使用Thread.Suspend和Resume方法。请注意,使用Suspend可能很危险(例如,线程可能在挂起之前已获得锁定)。由于这些问题,暂停/恢复被标记为绝对。