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
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
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?
Lies dir mal den zweiten Tipp von herbivore durch. Der sollte die Frage beantworten.
"Fehler sind das Tor zu neuen Entdeckungen"
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.
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
}
}
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?