2017-01-10 3 views
0

Ich brauche etwas Hilfe mit BackgroundWorker. Mit Visual Studio 2015 und seine Windows-FormulareTextBox nicht in Echtzeit aktualisiert über BackgroundWorker mit DataReceivedEventHandler aktiviert

Ich bin neu in dieser Art von Dingen und habe wirklich keine Ahnung, wie es funktioniert usw. Der Code, den ich bisher auf verschiedene Beiträge hier basiert basiert.

worker_DoWork_ wird überhaupt nicht gefeuert, aber keine Ahnung warum. Ich glaube, das hat etwas mit DataRceivedEventHandler zu tun, denn wenn ich das verschiebe, verschiebe ich den worker.DoWork + = worker_DoWork_; und worker.RunWorkerAsync(); In Button geklickt Ereignis und deaktivieren Sie DataReceivedEventHandler, Methode Worker_DoWork_ gefeuert und ich kann TextBox mit jedem statischen Text unter DoSomeWork zugewiesen aktualisieren.

Auch habe ich keine Ahnung, wie Sie über DoSomeWork Umriss Daten in das Textfeld übergeben.

Kann jemand bitte aushelfen.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Diagnostics; 
using System.Threading; 


namespace CMD_testing 
{ 
    public partial class Form1 : Form 
    { 
    BackgroundWorker worker; 
    private delegate void DELEGATE(); 

    public Form1() 
    { 
     InitializeComponent(); 
     worker = new BackgroundWorker(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 

     Process process; 
     process = new Process(); 
     process.StartInfo.FileName = @"C:\\Project\Test\Data.bat"; 
     process.StartInfo.UseShellExecute = false; 
     // process.StartInfo.CreateNoWindow = true; 
     process.StartInfo.RedirectStandardOutput = true; 
     process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); 

     process.StartInfo.RedirectStandardInput = true; 
     process.Start(); 
     process.BeginOutputReadLine(); 
     // process.WaitForExit(); 
     // process.Close(); 
    } 

    private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
    { 
     if (outLine.Data != null) 
     { 
      Console.WriteLine("Im here..."); 

      worker.DoWork += worker_DoWork_; 
      //worker.RunWorkerAsync(); 
      Console.WriteLine("Im here NOW"); 

      Console.WriteLine(outLine.Data); //its outputed fine into the console 
     } 

    } 

    private void worker_DoWork_(object sender, DoWorkEventArgs e) 
    { 
     Console.WriteLine("I'm at worker_DoWork_"); 
     Delegate del = new DELEGATE(DoSomeWork); 
     this.Invoke(del); 
    } 

    private void DoSomeWork() 
    { 
     Thread.Sleep(1000); 
     textBox1.Text = "????"; // how to pass outline.Data in here 

    } 

} 

}

+0

warum haben Sie kommentiert //worker.RunWorkerAsync(); ??? – NicoRiff

+0

weil ich einen Ausnahmefehler bekomme, der besagt, dass Backgroundworker bereits läuft und nicht gleichzeitig ausgeführt werden kann. Daher glaube ich, dass DataReceivedHandler eine von denen tritt, aber ich könnte falsch liegen –

+0

Sie müssen diese Zeile auskommentieren. Wenn du versuchst, es ein zweites Mal auszuführen, wird es zum Absturz kommen. Überprüfen Sie zunächst, ob (! Worker.IsBusy) {worker.RunWorkerAsync(); } - das erlaubt es nur zu laufen, wenn es gerade nicht läuft. –

Antwort

0

Das Problem ist, dass Sie RunWorkerAsync(); skizzieren. Diese Methode löst das DoWork-Event aus, das Ihren asynchronen Code behandelt. Über die EventArgs von DoWork können Sie Ihre Ergebnisse wieder auf Ihren Mainthread anwenden und in Ihre Textbox drucken. Sie können das Ergebnis im RunWorkerCompleted-Event erhalten. Hier ein kleines Beispiel, basierend auf Ihren Code:

public partial class Form1 : Form 
    { 
    BackgroundWorker worker; 

    public Form1() 
    { 
     InitializeComponent(); 
     worker = new BackgroundWorker(); 
     worker.DoWork += worker_DoWork; 
     worker.RunWorkerCompleted += worker_Completed; 
    } 

    private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
    { 
     if (outLine.Data != null) 
     { 
      if (!worker.IsBusy) //Check if Worker is working and avoid exception 
       worker.RunWorkerAsync();  
     } 
    } 

    private void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     //Process some Long-Running Task 
     Thread.Sleep(5000) 
     e.Result = "Done!"; 
    } 

    private void worker_Completed(object sender, RunWorkerCompletedEventArgs e) 
    { 
     textbox.Text = e.Result.ToString(); 
    } 
    } 
} 

Weitere sind Sie vielleicht Interesse an Task Library die den Umgang mit Themen zu erleichtern.

UPDATE:

Sie sagen:

ich meine Textbox in Echtzeit aktualisiert werden soll.

Dies wird den Text, den Ihre Batchdatei an Standardoutput sendet, direkt in Ihr Textfeld drucken. Also ich glaube nicht, dass du mehr brauchst.

private void OutputHandler(object sendingProcess, DataReceivedEventArgs e) 
    { 
     if (!string.IsNullOrWhiteSpace(e.Data)) 
      BeginInvoke(new MethodInvoker(() => { textBox1.Text = e.Data; })); 
    } 
+0

Danke, aber meine TextBox wird nicht in Echtzeit aktualisiert, d. H. Jedes Mal, wenn eine Zeile in das cmd-Fenster eingefügt wird. Es gibt nur "Fertig!" Aus. Irgendeine Idee warum? –

+0

@TomPisz Ihr Ziel ist mir nicht klar.Wenn Sie workers.RunWorkerAsync() aufrufen; Dadurch wird Ihr DoWork-Event einmal ausgeführt. Also sicher, es ergibt sich ein Done! in meinem Beispiel. Beachten Sie, dass Backgroundworker nicht bedeutet, dass Sie in Echtzeit arbeiten. Es gibt Ihnen nur die Fähigkeit einer reaktionsfähigen Benutzeroberfläche für lange laufende Operationen. – Sebi

+0

Sorry Sebi aber das habe ich auf diversen Webseiten und Foren gefunden. Ich muss das Textfeld in Echtzeit aktualisieren und jemand schlug vor, Hintergrund zu verwenden. Ich bin neu in C# und diese Art von Veranstaltungen so nicht so sicher, wie es geht und einfach versuchen und Fehler Ansatz. Kannst du mich in die richtige Richtung weisen? –

0

Dank @Sebi habe ich alle Probleme sortiert bekommen. Es stellt sich heraus, dass ich keinen BackgroundWorker brauche, wie einige Leute vorgeschlagen haben.

den endgültigen Code anzeigen, die wie ein Zauber funktioniert:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Diagnostics; 
using System.Threading; 


namespace CMD_testing 
{ 
    public partial class Form1 : Form 
    { 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 

     Process process; 
     process = new Process(); 
     process.StartInfo.FileName = @"C:\\Project\Test\Other Data.bat"; 
     process.StartInfo.UseShellExecute = false; 
      process.StartInfo.CreateNoWindow = true; 
     process.StartInfo.RedirectStandardOutput = true; 
     process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); 

     process.StartInfo.RedirectStandardInput = true; 
     process.Start(); 
     process.BeginOutputReadLine(); 
     process.Close(); 
    } 

    private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
    { 
     if (outLine.Data != null) 
     { 
      BeginInvoke(new MethodInvoker(() => { textBox1.AppendText(outLine.Data + Environment.NewLine); })); 
     } 

    } 
    } 

}

+0

Ich freue mich zu hören, dass Sie Ihre Probleme gelöst haben. – Sebi

Verwandte Themen