2011-08-16 12 views
6

Błąd: Object reference not set to an instance of an object.Dlaczego SynchronizationContext.Current null?

Poniższy algorytm działa. Próbowałem, a następnie usunąłem projekt Winform do innego katalogu i SynchronizationContext.Current jest null. Dlaczego?

SynchronizationContext uiCtx = SynchronizationContext.Current; 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    int[] makeSelfMoves = new int[4]; 

    lock (replay) 
    { 
     // count should be more than 2 
     foreach (KeyValuePair<int, int[]> item in replay) 
     {    
      makeSelfMoves = replay[item.Key]; 
      codeFile.ExecuteAll(makeSelfMoves[0], 
       makeSelfMoves[1], makeSelfMoves[2], makeSelfMoves[3]); 

      // i get the error here. uictx is null 
      uiCtx.Post(o => 
      { 
       PrintPieces(codeFile.PieceState()); 
      }, null);        

      System.Threading.Thread.Sleep(1000); 
     } 
    } 
} 
+3

Jakim kontekstem * * prowadzisz ten kod? Aplikacja konsolowa? –

+0

winform application –

+0

Co tworzy instancję tego obiektu i kiedy? (Wydaje się, że przechwytujesz kontekst synchronizacji * na konstrukcji *.) –

Odpowiedz

12

Kod krytycznie zależy od tego, kiedy dokładnie i gdzie konstruktor swoich tras klasowych. SynchronizationContext.Current będzie zerowy, gdy:

  • Twój obiekt klasy tworzony jest zbyt wcześnie, zanim kod tworzy instancję klasy Form lub wzywa Application.Run() w funkcji main(). To wtedy, gdy bieżący członek jest ustawiony na wystąpienie klasy WindowsFormsSynchronizationContext, klasa, która wie, jak zarządzać połączeniami za pomocą pętli komunikatów. Napraw to, przenosząc kod instancji obiektu do głównego konstruktora formularzy.

  • Twój obiekt klasy jest tworzony na dowolnym wątku innym niż główny wątek interfejsu użytkownika. Tylko wątek interfejsu użytkownika w aplikacji WinForm może generować połączenia. Diagnozowanie to przez dodanie do konstruktora klasy z tym stwierdzeniem:

     Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId); 
    

dodać również tę linię główną metodą() w Program.cs. Nie zadziała, jeśli wyświetlana wartość w oknie wyjściowym jest inna. Napraw to, przesuwając swój kod instancji obiektu do, ponownie, głównego konstruktora formularzy, aby mieć pewność, że działa on w wątku interfejsu użytkownika.

+0

w porządku, będę o tym pamiętać .. podziękowania za pomoc –

+0

To jest stara odpowiedź, ale warto zauważyć, że Application.Run nie jest jedynym czasem, gdy WinForm instaluje swój Kontekst Synchronizacji. Odkryłem, że tworzenie nowego formularza powoduje także instalację WindowsFormsSynchronizationContext i prawdopodobnie konstruktorzy innych podklas Control mają taki sam efekt, chociaż tego nie testowałem. – Drake

+0

Mam aplikację, w której faktycznie mam tylko 'new Control();' jako oświadczenie samo w sobie z komentarzem stwierdzającym, że jest to zrobione, ponieważ potrzebuję kontekst synchronizacji wcześniej niż byłoby inaczej utworzone. – hvd

Powiązane problemy