while the execution of a time consuming python script , i would manage the IU with background worker to display a progress bar.
i have used the background worker successfully when i needn't the event OutputDataReceived
, but the script that i'm using prints some progress values like ("10" , "80",..), so i got to listen the event OutputDataReceived
.
i get this error : This operation has already had OperationCompleted called on it and further calls are illegal.
in this line progress.bw.ReportProgress(v);
.
i tried to use 2 background worker instances, one executes and the other listens , it gives no errors but it seems do not call the event 'OutputDataReceived' so i don't see any progress in the progress bar.
below the code that i used:
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");
}
The problem is that the BackgroundWorker
's DoWork
handler finishes as soon as the process starts, as there's nothing "waiting" (since you commented out proc.WaitForExit()
) for the process to finish. Once the BackgroundWorker
work handler completes, you can no longer report progress using that instance.
Since Process.Start
is already asynchronous, there is no reason to use a background worker at all. You can just marshal the call from OutputDataReceived
onto the UI thread yourself:
///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;
}));
}
}
If you use this, don't create the BackgroundWorker
at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With