我正在使用以下代码测试计算机在出现问题之前可以处理的线程数:
static void Main(string[] args)
{
List<Thread> threads = new List<Thread>();
int count = 0;
try
{
while (true)
{
Console.Write('m'); // make
Thread thread = new Thread(() => { Thread.Sleep(Timeout.Infinite); }, 1024 * 64);
Console.Write('s'); // start
thread.Start();
Console.Write('p'); // suspend
thread.Suspend();
Console.Write('a'); // add
threads.Add(thread);
Console.Write(' ');
Console.WriteLine(count++);
}
}
catch (Exception e)
{
Console.WriteLine("\nGot exception of type " + e.GetType().Name);
}
Console.WriteLine(count);
Console.ReadKey(true);
}
我期望new Thread(...)
构造函数在系统无法创建更多线程时抛出异常(可能是OutOfMemoryException
),而是构造函数挂起并且永远不会返回。
而不是上面的输出
...
mspa 67
m
Got exception of type OutOfMemoryException
相当
...
mspa 67
m <- it hangs while 'm'aking the thread
所以,TLDR:为什么new Thread(...)
挂起而不是在线程太多时抛出异常?
答案 0 :(得分:6)
thread.Suspend();
这是一种邪恶的,邪恶的,邪恶的方法。在.NET 2.0版中被强烈弃用,你不清楚如何通过[Obsolete]消息并且没有注意到这一点。我将引用有关此方法的MSDN说明:
不要使用Suspend和Resume方法来同步线程的活动。暂停它时,您无法知道线程正在执行的代码。如果在安全权限评估期间挂起线程时挂起线程,则可能会阻止AppDomain中的其他线程。如果在执行类构造函数时挂起线程,则会阻止AppDomain中尝试使用该类的其他线程。死锁很容易发生。
是的,这就是死锁的样子。