2012-08-09 12 views
5

podczas wykonywania czasochłonnego skryptu python, będę zarządzać IU z pracującym w tle, aby wyświetlić pasek postępu.Proces w tle błędu pracownika

Użyłem pomyślnie pracownika tła, kiedy nie potrzebuję zdarzenia OutputDataReceived, ale skrypt, którego używam, wypisuje niektóre wartości postępu, takie jak ("10", "80", ..), więc muszę posłuchaj zdarzenia OutputDataReceived.

Otrzymuję ten błąd: This operation has already had OperationCompleted called on it and further calls are illegal. w tej linii progress.bw.ReportProgress(v);.

Próbowałem użyć 2 instancji tła, jedna wykonuje, a druga nasłuchuje, nie daje błędów, ale wygląda na to, że nie wywołuje zdarzenia "OutputDataReceived", więc nie widzę żadnego postępu na pasku postępu.

poniżej kod, który używany:

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

Czy wiesz, że C# 4 obsługuje Python nieco bardziej bezpośrednio? –

+0

Moje przeciwwskazanie do żelaznego pythona jest takie, że używam "Arcpy", więc wiążący pytajnik Arcpy to Iron nie jest dość łatwy. – geogeek

Odpowiedz

5

Problemem jest to, że BackgroundWorker „s DoWork obsługi kończy jak tylko rozpocznie się proces, ponieważ nie ma nic«czeka»(ponieważ wykomentowane proc.WaitForExit()) na proces do końca. Po zakończeniu pracy programu obsługi BackgroundWorker nie można już zgłaszać postępów przy użyciu tej instancji.

Od Process.Start jest już asynchroniczny, nie ma powodu, aby w ogóle używać pracownika tła. można po prostu zebrać rozmowa z OutputDataReceived na UI wątku siebie:

///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; 
     })); 
    } 
} 

Jeśli używasz tego nie tworzyć BackgroundWorker w ogóle.

+0

Twoje rozwiązanie wydaje się działać, ale myślę, że mam błąd na poziomie skryptu, ponieważ jego zachowanie zmienia się ze standardowego zachowania linii poleceń, więc dostał tylko 2 zdarzenia, jeden z pierwszą wartością "0", a drugi z wartością pustą, podczas gdy ja spodziewałem się 10 wartości int. – geogeek

Powiązane problemy