2011-08-16 23 views
6

Error: Object reference not set to an instance of an object.¿Por qué SynchronizationContext.Current es nulo?

El algoritmo siguiente funciona. Lo probé, luego eliminé el proyecto Winform en otro directorio y SynchronizationContext.Current es null. ¿Por qué?

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

¿En qué contexto * * está ejecutando este código entonces? Una aplicación de consola? –

+0

aplicación winform –

+0

¿Y qué está creando una instancia de este objeto y cuándo? (Parece que está capturando el contexto de sincronización * en la construcción * después de todo.) –

Respuesta

12

Su código depende críticamente de exactamente cuando y donde el constructor de las carreras de clase. SynchronizationContext.Current será nula cuando: se crea

  • su objeto de clase demasiado pronto, antes de que su código crea una instancia de la clase de formulario o llama Application.Run() en main(). Ahí es cuando el miembro actual se establece en una instancia de WindowsFormsSynchronizationContext, la clase que sabe cómo ordenar las llamadas con el bucle de mensajes. Arregle esto moviendo su código de instancia de objeto al constructor de formulario principal.

  • su objeto de clase se crea en cualquier hilo que no sea el hilo de la interfaz de usuario principal. Solo el hilo de UI en una aplicación Winforms puede ordenar llamadas. Diagnosticar esta añadiendo un constructor de su clase con esta declaración:

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

También añadir esta línea con el método() en Program.cs principal. No funcionará si el valor mostrado en la ventana de Salida es diferente. Arregle esto moviendo su código de instancia de objeto a, de nuevo, al constructor de formulario principal para que pueda estar seguro de que se ejecuta en el subproceso de interfaz de usuario.

+0

bien, voy a mantener su punto en mente ... gracias por la ayuda –

+0

Esta es una respuesta anterior, pero vale la pena señalar que Application.Run no es la única vez que WinForms instala su SynchronizationContext. He descubierto que la creación de un nuevo Formulario también da como resultado la instalación de WindowsFormsSynchronizationContext, y presumiblemente los constructores de otras subclases de Control tendrían el mismo efecto, aunque no he probado esto. – Drake

+0

Tengo una aplicación en la que en realidad solo tengo 'new Control();' como una declaración en sí misma con un comentario que indica que esto se hace porque necesito un contexto de sincronización antes de lo que se crearía de otra manera. – hvd

Cuestiones relacionadas