2017-01-03 1 views
4

Ich habe den folgenden einfachen Code:Task.Wait() wird nie zurückgegeben, wenn während der Initialisierung des statischen Felds aufgerufen wird?

class Program 
    { 
     public static readonly List<int> Years = BuildList(); 

     static void Main(string[] args) { } 

     private static List<int> BuildList() 
     { 
      var t = Task.Run(() => x()); 
      t.Wait(); 
      return new List<int>(); 
     } 

     private static void x() 
     { 
      Console.WriteLine("Hello World"); 
     } 
    } 

Nach Debuggen wird x() nie eingegeben und t.Wait() wird nie abgeschlossen/Returns und hängt für immer. Kann jemand dieses bizarre Verhalten erklären?

Es ist nicht wie es gibt UI blockierende Anrufe, alles was ich erraten kann ist, dass der Threadpool irgendwie ausgereizt ist?

Wenn ich den .Wait() Anruf entferne, dann wird schließlich x() eingegeben.

Beachten Sie, dass der Aufruf BuildList() von Main funktioniert einwandfrei.

+1

Needz Moar info – Liam

+4

Dies ist fraglos nicht das, was Sie tatsächlich tun, wenn das ist, was Sie sehen. Sie müssen ein Beispiel angeben, das Ihr Problem tatsächlich reproduzieren kann. Außerdem sollten Sie nie den 'Task'-Konstruktor verwenden. Verwenden Sie 'Task.Run', wenn Sie eine neue' Task' starten möchten, die die Arbeit in einem Thread-Pool-Thread darstellt. – Servy

+1

"Es ist nicht so, als gäbe es keine UI blockierenden Aufrufe" ... 't.Wait' _ist_ blockiert Ihren Haupt-Thread. Und 't.Start()' plant nur die Aufgabe, sie benutzt dafür keinen anderen Thread. –

Antwort

11

Im statischen Initialisierer für Program starten Sie einen neuen Thread und rufen eine Methode für die Klasse auf, für die Sie derzeit den statischen Initialisierer für ausführen. C# stellt sicher, dass eine Klasse genau einmal initialisiert wird. Wenn also zwei Threads versuchen, eine Klasse zu initialisieren, wartet einer darauf, dass der andere beendet wird. Da der Initialisierer darauf wartet, dass x beendet wird, bevor er fortgesetzt werden kann, und x darauf wartet, dass der Initialisierer beendet wird, bevor er ausgeführt werden kann, liegt ein Deadlock vor.

+0

Subtil aber genial. Ich mag die Erklärung. Etwas zum erinnern. –

Verwandte Themen