2010-11-06 4 views
0

Я мало знаю о C#.Запуск процесса в BackgroundWorker

Я пытаюсь отобразить панель прогресса со статусом программы командной строки.

После того, как Google progress progressbar и выполните процесс в C#, я пытаюсь запустить BackgroundWorker в Windows Form и запустить программу командной строки в BackgroundWorker. Я хочу проанализировать вывод командной строки, чтобы получить процентное соотношение и отобразить его в строке выполнения.

Программа командной строки представляет собой консольную программу, которая периодически выводит текущий статус прогресса.

Но, похоже, это не сработало. Я не могу читать строки строк стандартного вывода.

Есть ли что-нибудь, что я пропустил?

Вот исходный код:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Windows.Forms; 
using System.Drawing; 
using System.Threading; 
using System.Diagnostics; 
using System.IO; 


public class DemoForm : Form 
{ 
    private BackgroundWorker backgroundWorker1; 
    private Button loadButton; 
    private ProgressBar progressBar1; 

    public DemoForm() 
    { 
     InitializeComponent(); 

     backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); 
     backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(
       this.backgroundWorker1_DoWork); 
     backgroundWorker1.RunWorkerCompleted += 
      new System.ComponentModel.RunWorkerCompletedEventHandler(
        this.backgroundWorker1_RunWorkerCompleted); 
     backgroundWorker1.ProgressChanged += 
      new System.ComponentModel.ProgressChangedEventHandler(
        this.backgroundWorker1_ProgressChanged); 

    } 

    private void loadButton_Click(object sender, EventArgs e) 
    { 
     backgroundWorker1.RunWorkerAsync(); 

     this.loadButton.Enabled = false; 
    } 

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     string status; 
     Process p = new Process(); 
     p.StartInfo.FileName = "xx.exe"; 
     p.StartInfo.Arguments = "-q -r test.cap -p"; 
     p.StartInfo.UseShellExecute = false; 
     p.StartInfo.RedirectStandardOutput = true; 
     p.StartInfo.CreateNoWindow = true; 
     p.OutputDataReceived += this.p_OutputDataReceived; 
     p.EnableRaisingEvents = true; 
     p.Start(); 
     p.BeginOutputReadLine(); 

/* 
     while((status = p.StandardOutput.ReadLine()) != null) 
     { 
      Console.WriteLine(status); 
      string[] words = status.Split(' '); 
      int offset = Convert.ToInt32(words[0]); 
      int size = Convert.ToInt32(words[1]); 

      int percentComplete = 100 * offset/size; 
      MessageBox.Show(words[0], words[1]); 
      backgroundWorker1.ReportProgress(percentComplete); 
     } 
     Console.WriteLine("wait for exit!"); 
     StreamReader myStreamReader = p.StandardOutput; 
     status = myStreamReader.ReadLine(); 
     Console.WriteLine(status); 
     Console.WriteLine("wait for exit!"); 
     */ 
     p.WaitForExit(); 
    } 

    void p_OutputDataReceived(object sender, DataReceivedEventArgs e) 
    { 
     string status = e.Data; 
     Console.WriteLine("get events"); 
     Console.WriteLine(status); 
     string[] words = status.Split(' '); 
     int offset = Convert.ToInt32(words[0]); 
     int size = Convert.ToInt32(words[1]); 

     int percentComplete = 100 * offset/size; 
     MessageBox.Show(words[0], words[1]); 
     backgroundWorker1.ReportProgress(percentComplete); 
    } 

    private void backgroundWorker1_RunWorkerCompleted(object sender, 
      RunWorkerCompletedEventArgs e) 
    { 
     progressBar1.Value = 100; 
     if (e.Error == null) { 
      MessageBox.Show ("Demo", "Loading completed"); 
     } 
    } 

    private void backgroundWorker1_ProgressChanged(object sender, 
      ProgressChangedEventArgs e) 
    { 
     this.progressBar1.Value = e.ProgressPercentage; 
    } 

    private System.ComponentModel.IContainer components = null; 

    protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

    private void InitializeComponent() 
    { 
     this.loadButton = new System.Windows.Forms.Button(); 
     this.progressBar1 = new System.Windows.Forms.ProgressBar(); 

     /* load button */ 
     this.loadButton.Location = new System.Drawing.Point(12, 12); 
     this.loadButton.Name = "loadButton"; 
     this.loadButton.Size = new System.Drawing.Size(100, 23); 
     this.loadButton.TabIndex = 0; 
     this.loadButton.Text = "Load file"; 
     this.loadButton.UseVisualStyleBackColor = true; 
     this.loadButton.Click += new System.EventHandler(this.loadButton_Click); 

     /* progress bar */ 
     this.progressBar1.Location = new System.Drawing.Point(12, 50); 
     this.progressBar1.Name = "progressBar1"; 
     this.progressBar1.Size = new System.Drawing.Size(100, 26); 
     this.progressBar1.TabIndex = 1; 

     /* Form */ 
     this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
     this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
     this.ClientSize = new System.Drawing.Size(133, 104); 
     this.Controls.Add(this.progressBar1); 
     this.Controls.Add(this.loadButton); 
     this.Name = "DemoForm"; 
     this.Text = "DemoForm"; 
     this.ResumeLayout (false); 
    } 
} 

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.Run(new DemoForm()); 
    } 
} 

Или есть лучший способ получить прогресс программы командной строки, в?

+0

Что это за процесс, в котором вы работаете? Это консольное приложение? Как он мог сообщить о прогрессе? –

+0

Это только я или это часть комментария, которая делает обновление? – rtpg

+0

@Dasuraga true! – gideon

ответ

1

После вручную удалить вывод программы командной строки, проблема решена.

fflush(stdout); 

Непонятно, почему это забуферировано, даже закончилась линия.

+1

Недавно я столкнулся с очень похожей проблемой. Причина этого объясняется paxdiablo здесь: http://stackoverflow.com/questions/1716296/why-does-printf-not-flush-after-the-call-unless-a-newline-is-in-the- формат-Strin – hofan41

2

Вы должны установить WorkerReportsProgress свойство вашего BackgroundWorker к истине, чтобы быть в состоянии сообщить, пока ваш BackgroundWorker работает:

backgroundWorker1.WorkerReportsProgress = true; 
+0

Кажется, до сих пор я не могу получить какой-либо результат ... до достижения отчета. –

+0

Это не тот вопрос. – SHAHS

1

Основываясь на том, что указывал Камяр, вам нужно будет затем закодировать делегата, чтобы захватить прогресс вашего объекта backgroundWorker с помощью объекта UserState. Это может быть любой объект, на самом деле, но вы используете его, чтобы обновить другие аспекты графического интерфейса пользователя, в данном случае этикетки статус ...

this.backgroundWorker1.WorkerReportsProgress = true; 
this.backgroundWorker1.WorkerSupportsCancellation = true; 
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork); 
this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged); 
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted); 

private class Progress 
{ 
    public string Status { get; set; } 
    public Progress(string status) 
    { 
     Status = status; 
    } 
} 

//... 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    while(myWork) 
    { 
     if(backgroundWorker1.CancellationPending) 
     { 
     e.Cancel = true; 
     break; 
     } 

     int p = //...percentage calc 
     backgroundWorker1.ReportProgress(p, new Progress("My message..."))); 
    } 

    e.Cancel = false; 
} 

void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
     Progress p = (Progress)e.UserState; 
     lStatus.Text = p.Status; 
     progressBar.Value = e.ProgressPercentage; 
} 

Это только один способ его реализации, хотя.

Спасибо.

Смежные вопросы