2011-08-16 15 views
6

Errore: Object reference not set to an instance of an object.Perché SynchronizationContext.Current è null?

L'algoritmo seguente funziona. ho provato, poi ho tolto il progetto Winform in un'altra directory e SynchronizationContext.Current è null. Perché?

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

quale contesto * è * si esegue questo codice in poi? Un'app per console? –

+0

winform application –

+0

E cosa sta creando un'istanza di questo oggetto e quando? (Sembra che tu stia catturando il contesto di sincronizzazione * * sulla costruzione dopo tutto.) –

risposta

12

Il codice dipende in modo critico da quando e dove viene eseguito il costruttore della classe. SynchronizationContext.Current sarà nulla quando:

  • l'oggetto classe viene creata troppo presto, prima che il codice crea un'istanza della classe Form o chiama Application.Run() in Main(). Quello è quando il membro Corrente è impostato su un'istanza di WindowsFormsSynchronizationContext, la classe che sa come effettuare il marshalling delle chiamate con il loop dei messaggi. Risolvi questo problema spostando il codice di istanza dell'oggetto nel costruttore di moduli principale.

  • l'oggetto classe viene creata su qualsiasi thread diverso dal thread principale dell'interfaccia utente. Solo il thread dell'interfaccia utente in un'applicazione Winforms può effettuare il marshalling delle chiamate. Diagnosticare questo con l'aggiunta di un costruttore per la classe con questa affermazione:

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

aggiungere anche questa linea per il metodo() in Program.cs principale. Non funzionerà se il valore visualizzato nella finestra Output è diverso. Risolvi questo problema spostando il codice di istanza dell'oggetto su, di nuovo, il costruttore di moduli principale in modo da poter essere sicuro che venga eseguito sul thread dell'interfaccia utente.

+0

va bene, terrò il tuo punto mind..thanks per l'aiuto –

+0

Questa è una risposta vecchia, ma vale la pena notare che Application.Run non è il solo WinForms tempo installa la sua SynchronizationContext. Ho scoperto che la creazione di un nuovo form comporta anche l'installazione di WindowsFormsSynchronizationContext, e presumibilmente i costruttori di altre sottoclassi di Control avrebbero lo stesso effetto, sebbene non l'abbia provato. – Drake

+0

Ho un'applicazione in cui effettivamente ho appena 'nuovo Control();' come una dichiarazione tutto da solo con un commento che afferma che ciò è fatto perché ho bisogno di un contesto di sincronizzazione prima di quello che sarebbe altrimenti creato. – hvd

Problemi correlati