It is generally dangerous to call threading code from a static constructor. In order to ensure that the static constructor executes only once, the CLR executes the static constructor under a lock. If the thread running the static constructor waits on a helper thread, there is a risk that the helper thread is going to need the CLR-internal lock for some reason too, and the program will deadlock.
Here is a simpler code sample that demonstrates the problem:
using System.Threading;
class Blah
{
static void Main() { /* Won’t run because the static constructor deadlocks. */ }
static Blah()
{
Thread thread = new Thread(ThreadBody);
thread.Start();
thread.Join();
}
static void ThreadBody() { }
}
Section 10.5.3.3 "Races and deadlocks" of the ECMA CLI spec guarantees the following:
Type initialization alone shall not create a deadlock unless some code
called from a type initializer (directly or indirectly) explicitly
invokes blocking operations.
So, a type initializer (i.e., a static constructor) will not deadlock, provided that no operation in the static constructor blocks the thread. If the static constructor does block, it risks a deadlock.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…