Laden...

Progress Window aus Thread oder Backgroundworker steuern

Erstellt von j0nas vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.600 Views
J
j0nas Themenstarter:in
45 Beiträge seit 2009
vor 14 Jahren
Progress Window aus Thread oder Backgroundworker steuern

Hallo zusammen

Mein Problem ist folgendes: Ich arbeite an einem Tool das für gewisse Dinge länger braucht. Damit das Programm nicht einfach "einfriert" habe ich dazu einen Thread erstellt. Nun habe ich mir das so gedacht das ich vor dem Aufruf des Threads ein Fenster öffne dass immer im Fordergrund bleibt. Auf diesem Fenster soll ersichtlich sein was gerade gemacht wird (das sollte aus dem Thread üübergeben werden). Leider kann ich das nicht so umsetzen wie ich das gerne hätte :S

Hie mal mein Code (ich habs mit nem Backgroundworker gemacht)

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

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

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        int iWorkToDo = 10;

        frmProgress frmProgress = new frmProgress();
        frmProgress.Show();

        for (int i = 0; i < iWorkToDo; i++)
        {
            System.Threading.Thread.Sleep(1000);
        }

        frmProgress.Close();
    }
}

Mein Vorhaben scheitert schon daran das frmProgress nach dem öffnen einfriert.
Könnt ihr mir ein paar Tipps oder Codeschnipsel geben?

Vielen Dank

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo j0nas,

du musst frmProgress im GUI-Thread erzeugen.

Siehe auch [FAQ] Warum blockiert mein GUI? und [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke).

herbivore

J
j0nas Themenstarter:in
45 Beiträge seit 2009
vor 14 Jahren

Hmm vielleicht hab ichs ja übersehen aber wie kann z.B. ein Label des neuen Fensters aus dem Thread hinaus ansteuern? Und wie kann ich das Form schliessen nachdem der Thread beendet ist?

B
76 Beiträge seit 2007
vor 14 Jahren

Lies dir mal den zweiten Tipp von herbivore durch. Der sollte die Frage beantworten.

"Fehler sind das Tor zu neuen Entdeckungen"

4.938 Beiträge seit 2008
vor 14 Jahren

Sieh dir hierzu die Ereignisse ProgressChanged und RunWorkerCompleted in der MSDN an.

P.S. Für einen Backgroundworker ist kein Invoke nötig, da die beiden obigen Ereignisse automatisch schon im GUI-Thread ausgeführt werden.

J
j0nas Themenstarter:in
45 Beiträge seit 2009
vor 14 Jahren

Jetzt hab ich das, kann mir jemand sagen wies weitergehen soll?

private void btnDowork_Click(object sender, EventArgs e)
{
    frmProgress progress = new frmProgress();
    progress.Show();
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    int iWorkToDo = 6;

    for (int i = 0; i < iWorkToDo; i++)
    {
        System.Threading.Thread.Sleep(1000);

        backgroundWorker1.ReportProgress(IRGENDWAS);
    }
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // label von progress ändern
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // progress schliessen
}

}
J
j0nas Themenstarter:in
45 Beiträge seit 2009
vor 14 Jahren

Habe mir da mal was zusamengebastelt:

Hauptformular:

frmShow _formProgressBar = new frmShow();

public frmMain()
{
    InitializeComponent();
}


private void btnStart_Click(object sender, EventArgs e)
{
    Start();
}


private void Start()
{
    Thread _workerThread = null;  

    _formProgressBar.Show();

    _workerThread = new Thread(new ThreadStart(Workerthread));
    _workerThread.Start();
    
}

private void Workerthread()
{

    this.Invoke(new frmShow.SetTask1Delegate(_formProgressBar.SetTask1), new object[] { "mach was" });
    System.Threading.Thread.Sleep(1200); 
    this.Invoke(new frmShow.SetTask1Delegate(_formProgressBar.SetTask1), new object[] { "tu was" });
    System.Threading.Thread.Sleep(300);
    this.Invoke(new frmShow.SetTask1Delegate(_formProgressBar.SetTask1), new object[] { "irgendwas" });
    System.Threading.Thread.Sleep(500);
    this.Invoke(new frmShow.SetTask1Delegate(_formProgressBar.SetTask1), new object[] { "tacheles" });
    System.Threading.Thread.Sleep(800);
    this.Invoke(new frmShow.SetTask1Delegate(_formProgressBar.SetTask1), new object[] { "ich esse blumen" });
    System.Threading.Thread.Sleep(1400);
    this.Invoke(new frmShow.SetTask1Delegate(_formProgressBar.SetTask1), new object[] { "bis dann jann" });
    System.Threading.Thread.Sleep(800);
    this.Invoke(new frmShow.SetTask1Delegate(_formProgressBar.SetTask1), new object[] { "hehe" });
    System.Threading.Thread.Sleep(1000);

    this.Invoke(new endeDelegate(ende), new object[] { });
}


delegate void endeDelegate();

private void ende()
{
    _formProgressBar.Hide();
}

frmShow:

public partial class frmShow : Form
{
    public frmShow()
    {
        InitializeComponent();
    }

    public delegate void SetTask1Delegate(string strString);

    public void SetTask1(string strString)
    {
        if (this.lblWhat.InvokeRequired)
        {
            SetTask1Delegate d = new SetTask1Delegate(SetTask1);
            Invoke(d, new object[] { strString });
        }
        else
        {
            lblWhat.Text = String.Format(strString);
        }     
    }


}

was ich allerdings noch nicht geschaft habe ist das frmShow immer vor dem hauptformular bleibt. Tipps?