2012-08-09 11 views
5

Mientras ejecutaba un script python lento, administraría la IU con el trabajador de fondo para mostrar una barra de progreso.Proceso en error de trabajador de fondo

he utilizado el trabajador de fondo con éxito cuando no necesito el evento OutputDataReceived, pero el script que estoy usando imprime algunos valores de progreso como ("10", "80", ..), así que tuve que escucha el evento OutputDataReceived.

consigo este error: This operation has already had OperationCompleted called on it and further calls are illegal. en esta línea progress.bw.ReportProgress(v);.

intenté utilizar 2 instancias de fondo de trabajo, una se ejecuta y la otra escucha, no da ningún error pero parece que no se llama al evento 'OutputDataReceived' por lo que no veo ningún progreso en la barra de progreso.

debajo del código que he utilizado:

private void execute_script() 
    { 
      progress.bw.DoWork += new DoWorkEventHandler(//progress.bw is reference to the background worker instance 
     delegate(object o, DoWorkEventArgs args) 
     { 

     System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
     proc.StartInfo.FileName = "python.exe"; 
     proc.StartInfo.UseShellExecute = false; 
     proc.StartInfo.Arguments = @".\scripts\script1.py " + file_path + " " + txtscale.Text; 
     //proc.StartInfo.CreateNoWindow = true; 
     //proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
     proc.StartInfo.RedirectStandardOutput = true; 
     //proc.EnableRaisingEvents = true; 
     proc.StartInfo.RedirectStandardError = true; 
     proc.StartInfo.RedirectStandardError = true; 
     proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OutputDataReceived); 
     proc.Start(); 
     proc.BeginOutputReadLine(); 

     //proc.WaitForExit(); 
     //proc.Close(); 
        }); 

      progress.bw.RunWorkerAsync(); 
     } 

///the function called in the event OutputDataReceived 
void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) 
    { 
     //throw new NotImplementedException(); 
     if (e.Data != null) 
     { 
      int v = Convert.ToInt32(e.Data.ToString()); 
      MessageBox.Show(v.ToString()); 
     // report(v); 
      progress.bw.ReportProgress(v); 

     } 
     else 
      MessageBox.Show("null received"); 


    } 
+1

Usted sabe que C# 4 es compatible con Python un poco más directamente? –

+0

mi contraint a ironpython es que, estoy usando "ArcPy" por lo que la unión ArcPy a ironpython no es bastante fácil. – geogeek

Respuesta

5

El problema es que el BackgroundWorker 's DoWork manipulador termina tan pronto como se inicia el proceso, ya que no hay nada 'espera'(ya que comentada proc.WaitForExit()) para que el proceso finalice. Una vez que el controlador de BackgroundWorker trabajo completa, ya no se puede informar sobre el progreso usando esa instancia.

Desde Process.Start ya es asíncrona, no hay razón para usar un trabajador de fondo en absoluto. Usted sólo puede reunir la llamada de OutputDataReceived en la interfaz de usuario de hilo de sí mismo:

///the function called in the event OutputDataReceived 
void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) 
{ 
    //throw new NotImplementedException(); 
    if (e.Data != null) 
    { 
     int v = Convert.ToInt32(e.Data.ToString()); 
     // MessageBox.Show(v.ToString()); 
     // progress.bw.ReportProgress(v); 
     this.BeginInvoke(new Action(() => { 
      this.progressBar.Value = v; 
     })); 
    } 
} 

Si utiliza esto, no crean la BackgroundWorker en absoluto.

+0

su solución parece funcionar, pero creo que tengo un error en el nivel de script, porque su comportamiento cambia del comportamiento de línea de comandos estándar, por lo que obtuvo solo 2 eventos uno con el primer valor "0" y el segundo con valor nulo, mientras estoy esperando 10 valores de int. – geogeek

Cuestiones relacionadas