我正在使用以下代码测试出现问题之前计算机可以处理的线程数:
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);
}
Run Code Online (Sandbox Code Playgroud)
当系统无法创建更多线程时,我被期望new Thread(...)构造函数抛出异常(可能OutOfMemoryException),而构造函数挂起并且永远不会返回.
而不是上面的输出
...
mspa 67
m
Got exception of type OutOfMemoryException
Run Code Online (Sandbox Code Playgroud)
相反
...
mspa 67
m <- it hangs while 'm'aking the thread
Run Code Online (Sandbox Code Playgroud)
那么,TLDR:为什么new Thread(...)挂起而不是在线程太多时抛出异常?
thread.Suspend();
Run Code Online (Sandbox Code Playgroud)
这是一种邪恶,邪恶,邪恶的方法.在.NET 2.0版中大力弃用,你不清楚如何通过[Obsolete]消息并且没有注意到这一点.我将引用有关此方法的MSDN说明:
不要使用Suspend和Resume方法来同步线程的活动.暂停它时,您无法知道线程正在执行的代码.如果在安全权限评估期间挂起线程时挂起线程,则可能会阻止AppDomain中的其他线程.如果在执行类构造函数时挂起线程,则会阻止AppDomain中尝试使用该类的其他线程.死锁很容易发生.
是的,这就是死锁的样子.