Entwickler-Ecke
C# - Die Sprache - Stoppuhr mit Threads Programmieren
nellyville - Mo 05.01.09 16:09
Titel: Stoppuhr mit Threads Programmieren
Hallo Leute ich bekam heute von meinem Lehrmeister einen Auftrag ich sollte eine Stoppuhr welche 2 Messwerte hat mit Threads programmieren dabei sollte die Stoppuhr mit einem Button gestartet werden und sollte sich raufzählen 1,2,3,4,5,6,7,8,9,10 usw während dem die 1 te Stoppuhr läuft sollte ich die 2 Stoppuhr laufen lassen können , welche sich auch wieder raufzählt wie z.b 1,2,3,4,5,6,7,8,9..
Hat jemand eine Idee wie ich das ganze programmieren kann ? ich kann mir das ganze nicht ganz vorstellen und würde sehr froh wenn ihr mir ein bisschen auf die Sprünge helfen könntet.
Freundliche Grüsse
sharpx - Mo 05.01.09 16:31
öhm....
eigentlich doch alles klar oder?
2 buttons:
stoppuhr 1
stoppuhr 2
1 funktion
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| public static void counter () { for (int i=0; i<120; i++) { field.Text = i.ToString(); System.Threading.Thread.Sleep(1000); } } |
Jetzt bindest du pro button einen funktionsaufruf und machst je einen thread draus ...
das wars dann auch schon.
Die andere frage ist natürlich wie "genau" diese "Stoppuhr" dann ist.
Weder die Sleep Anweisung noch die Threads sind ja im prinzip echtzeit, außer du hast jetzt wirklich 2 CPUS in der Maschine und kannst das aufteilen. Die CPU springt auch in millionstensekunden tag zwischen den threads hin und her.
ABer vom Prinzip her sollte wohl alles klar sein?
Moderiert von
Christian S.: C#-Tags hinzugefügt
jaenicke - Mo 05.01.09 16:35
Richtige Zeitmessung wäre einfacher und genauer...
nellyville - Mo 05.01.09 16:47
sharpx hat folgendes geschrieben : |
öhm....
eigentlich doch alles klar oder?
2 buttons:
stoppuhr 1
stoppuhr 2
1 funktion
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| public static void counter () { for (int i=0; i<120; i++) { field.Text = i.ToString(); System.Threading.Thread.Sleep(1000); } } |
Jetzt bindest du pro button einen funktionsaufruf und machst je einen thread draus ...
das wars dann auch schon.
Die andere frage ist natürlich wie "genau" diese "Stoppuhr" dann ist.
Weder die Sleep Anweisung noch die Threads sind ja im prinzip echtzeit, außer du hast jetzt wirklich 2 CPUS in der Maschine und kannst das aufteilen. Die CPU springt auch in millionstensekunden tag zwischen den threads hin und her.
ABer vom Prinzip her sollte wohl alles klar sein? |
soo hab das ganze mal versucht zu programmieren
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| using System; using System.Collections.Generic;
using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading;
namespace Stoppuhr { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public static void counter() { for (int i = 0; i < 120; i++) { Feld1.Text = i.ToString(); System.Threading.Thread.Sleep(1000); } }
private void button1_Click(object sender, EventArgs e) { Thread[] ta = new Thread[120]; for (int j = 0; j < 120; j++) { ta[j] = new Thread(new ThreadStart(counter)); ta[j].Start(); } }
private void button2_Click(object sender, EventArgs e) { Thread[] ta1 = new Thread[120]; for (int j1 = 0; j1 < 120; j1++) { ta1[j1] = new Thread(new ThreadStart(counter)); ta1[j1].Start(); } } } } |
bekomme nur noch einen Fehler bei meinem Textbox namens Feld1 :S
Fehler 1 Für das nicht statische Feld, die Methode oder die Eigenschaft "Stoppuhr.Form1.Feld1" ist ein Objektverweis erforderlich. Projects\Stoppuhr\Form1.cs 17 21 Stoppuhr
Moderiert von
Christian S.: C#-Tags hinzugefügt
nellyville - Mo 05.01.09 17:20
Beim folgenden Objektverweis glaube ich dass der Fehler beim TextBox Feld liegt wisst ihr was ich machen muss z.b ein anderes Feld wählen ? Wenn ja welches ? oder woaran liegt der Fehler ich kann es nicht herausfinden
jaenicke - Mo 05.01.09 17:39
"counter" ist als static deklariert und damit nicht auf eine bestimmte Instanz bezogen sondern auf die Klasse. Und deshalb kannst du natürlich auch nicht auf ein bestimmtes erzeugtes Feld einer bestimmten Instanz der Klasse zugreifen. ;-)
nellyville - Di 06.01.09 09:27
jaenicke hat folgendes geschrieben : |
"counter" ist als static deklariert und damit nicht auf eine bestimmte Instanz bezogen sondern auf die Klasse. Und deshalb kannst du natürlich auch nicht auf ein bestimmtes erzeugtes Feld einer bestimmten Instanz der Klasse zugreifen. ;-) |
So vielen Dank das Programm läuft mal Fehlerfrei doch es erfüllt immer noch nicht das was ich mir vorstelle. Wenn ich den Startbutton anklicke dann läuft das Programm einfach durch ohne irgendwelche werte in der TextBox anzuzeigen. Könnte man das ganze auch anderst lösen ? Mein Code :
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43:
| using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading;
namespace Stoppuhr { public partial class Form1 : Form { public Form1() { InitializeComponent(); } int i = 0; public void counter() { for (int i = 0; i < 120; i++) { Feld1.Text = i.ToString(); System.Threading.Thread.Sleep(1000); } }
private void button1_Click(object sender, EventArgs e) { Thread[] ta = new Thread[120]; for (int j = 0; j < 120; j++) { ta[j] = new Thread(new ThreadStart(counter)); ta[j].Start(); } }
private void button2_Click(object sender, EventArgs e) { Thread[] ta1 = new Thread[120]; for (int j1 = 0; j1 < 120; j1++) { ta1[j1] = new Thread(new ThreadStart(counter)); ta1[j1].Start(); } }
} } |
jaenicke - Di 06.01.09 14:38
Was ich mich frage: Wozu brauchst du 120 Threads :?:
nellyville - Di 06.01.09 14:41
das ganze habe ich aus einem anderen Thread beispiel raus zusammengeschnipselt kopiert. Ja da hast du recht ich brauche doch nur 2 Threads oder ? Habe keine Übersicht über die Ganze Sache bin ziemlich Neu wenn es um die Threads geht :S
jaenicke - Di 06.01.09 14:46
Außerdem kannst du aus einem Thread so nicht auf das Textfeld zugreifen glaube ich, schließlich wurde das im Hauptthread erstellt. Aber da habe ich in C# zu wenig Erfahrung um genau zu sagen wie das richtig geht.
Ich probiere es mal aus bzw. schaue mal in die Doku.
nellyville - Di 06.01.09 15:04
Ja eben darüber habe ich auch gedacht wie es überhaupt möglich wäre einen Textfeld über einen Thread zu steuern ich freue mich über jede hilfe :S
nellyville - Di 06.01.09 15:27
okey ich schau mir mal das ganze an vielen dank ;)
Christian S. - Di 06.01.09 15:32
Davon würde ich
dringend abraten! Wenn der Aufruf dann schief geht, sucht man sich wahrscheinlich tot, um den Fehler zu finden.
Der korrekte Weg ist über den Aufruf von
Invoke. Dem übergibt man die Methode, welche im GUI-Thread ausgeführt werden soll. In Prism sieht's dann (mit anonymer Methode) so aus:
Delphi Prism
1: 2: 3:
| Invoke(method; begin textBox1.Text := 'foo'; end); |
Anonyme Methoden funktionieren an der Stelle auch in C# und erhöhen die Übersicht an dieser Stelle sehr, weil's fast so aussieht, als würde der Befehl wirklich an der Stelle ausgeführt ;-)
jaenicke hat folgendes geschrieben : |
Dass es dort aber überhaupt diese Fehlermeldung gibt, heißt für mich jedenfalls, dass es in C# bzw. .NET genauso nicht korrekt ist einfach aus dem Thread auf die Textbox zuzugreifen (wie ich es aus Delphi kenne). |
Röschtösch!
nellyville - Di 06.01.09 15:42
Ich hab mal das Beispiel programm winformthreading ausprobiert und ich sehe das ist eigentlich genau das was ich gesucht habe vielen dank Leute ;)
nellyville - Di 06.01.09 17:16
So ich hab mal mich mit dem Sourcecode von dem Tool ThreadExample (
http://www.codeproject.com/KB/cs/threadingandui.aspx) auseinander gesetzt , doch ich verstehe den Code nicht kann mir jemand weiterhelfen ?
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62:
| using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms;
namespace ThreadExample { public partial class Form1 : Form { PerformLongComputation per = new PerformLongComputation(); private delegate void callUIUpdater(ReportProgress args); public Form1() { InitializeComponent(); per.OnUpdateProgress += new EventHandler<ReportProgress>(per_OnUpdateProgress); } public void goDoWork(object sender) { if (txt_num.Text != "") { per.DoComputation(int.Parse(txt_num.Text.ToString())); } else { MessageBox.Show("Text box is empty"); } }
private void btn_compute_Click(object sender, EventArgs e) {
per.stopComputation(false); System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(this.goDoWork));
} private void per_OnUpdateProgress(object sender , ReportProgress e) { if (InvokeRequired) Invoke(new callUIUpdater(UpdateUI), e); else UpdateUI(e);
} private void UpdateUI(ReportProgress e) { label1.Text = e.CurrentStatus.GetCurrentVAlue.ToString() + " OF " + e.CurrentStatus.GetNumOfIteration.ToString(); Invalidate(true); Update(); }
private void btn_cancel_Click(object sender, EventArgs e) { per.stopComputation(true); }
} } |
nellyville - Mi 07.01.09 09:30
Habe mal die verschiedenen Funktionen und Befehle im Internet durchsucht doch nichts gefunden was mir klar machen konnte für was die verschiedenen Funktionen stehen.
Ich änderte beim Programm WinFormThreading ,welches sich auf 100 raufzählt und man gleichzeitig immer einen Messagebox durch einen buttonklick hervorrufen kann,die zahl hundert auf 150 um und bekam den Folgenden Fehler System.Reflection.TargetInvocationexception {"Ein Aufrufziel hat einen Ausnahmefehler verursacht."} im Application.Run(new Form1());
Brauche Hilfe :(
Hier noch der sourcecode vom WinFormThreading
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191:
| using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Threading;
namespace WinFormThreading { public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Button button1; private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Button button2; private System.Windows.Forms.CheckBox cbThreadPool; private System.Windows.Forms.ProgressBar progressBar1; private System.ComponentModel.Container components = null;
public Form1() { InitializeComponent();
}
protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); }
#region Windows Form Designer generated code private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.textBox1 = new System.Windows.Forms.TextBox(); this.button2 = new System.Windows.Forms.Button(); this.cbThreadPool = new System.Windows.Forms.CheckBox(); this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.SuspendLayout(); this.button1.Location = new System.Drawing.Point(24, 56); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(88, 24); this.button1.TabIndex = 0; this.button1.Text = "Start.."; this.button1.Click += new System.EventHandler(this.button1_Click); this.textBox1.Location = new System.Drawing.Point(24, 24); this.textBox1.Name = "textBox1"; this.textBox1.ReadOnly = true; this.textBox1.Size = new System.Drawing.Size(100, 20); this.textBox1.TabIndex = 1; this.textBox1.Text = "--"; this.button2.Location = new System.Drawing.Point(120, 56); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(88, 24); this.button2.TabIndex = 1; this.button2.Text = "Click Me.."; this.button2.Click += new System.EventHandler(this.button2_Click); this.cbThreadPool.Location = new System.Drawing.Point(136, 24); this.cbThreadPool.Name = "cbThreadPool"; this.cbThreadPool.Size = new System.Drawing.Size(104, 24); this.cbThreadPool.TabIndex = 3; this.cbThreadPool.Text = "ThreadPool"; this.progressBar1.Location = new System.Drawing.Point(32, 88); this.progressBar1.Name = "progressBar1"; this.progressBar1.Size = new System.Drawing.Size(184, 23); this.progressBar1.TabIndex = 4; this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(272, 118); this.Controls.Add(this.progressBar1); this.Controls.Add(this.cbThreadPool); this.Controls.Add(this.button2); this.Controls.Add(this.textBox1); this.Controls.Add(this.button1); this.Name = "Form1"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "WinForm Threading"; this.ResumeLayout(false); this.PerformLayout();
} #endregion
[STAThread] static void Main() { Application.Run(new Form1()); }
delegate void ShowProgressDelegate ( int totalMessages, int messagesSoFar, bool statusDone );
private void button1_Click(object sender, System.EventArgs e) {
ShowProgressDelegate showProgress = new ShowProgressDelegate(ShowProgress); int imsgs = 105;
if ( cbThreadPool.Checked ) { object obj = new object[] { this, showProgress, imsgs }; WorkerClass wc = new WorkerClass(); bool rc = ThreadPool.QueueUserWorkItem( new WaitCallback (wc.RunProcess), obj); EnableButton( ! rc ); } else { WorkerClass wc = new WorkerClass( this, showProgress, new object[] { imsgs } ); Thread t = new Thread( new ThreadStart(wc.RunProcess)); t.IsBackground = true; t.Start(); EnableButton ( false ); } }
private void EnableButton ( bool flag ) { button1.Enabled = flag; } private void ShowProgress ( int totalMessages, int messagesSoFar, bool done ) { textBox1.Text = String.Format( messagesSoFar.ToString() ); progressBar1.Value = messagesSoFar; if ( done ) EnableButton ( done ); }
private void button2_Click(object sender, System.EventArgs e) { MessageBox.Show("You clicked me!"); }
} } |
jaenicke - Mi 07.01.09 12:56
Ich hatte gehofft, dass jemand anderes antwortet (*auffordernd in die Runde schaut* :D), weil ich selbst es eben wie gesagt nicht auswendig weiß. Ich muss immer selbst erst nachschauen und suchen wie das funktioniert. (Habe damit aber auch kaum Probleme. ;-))
Ich schau mir den Code mal an. ;-)
nellyville - Mi 07.01.09 15:37
vielen dak für deine Hilfe ich verstehe den code wirklich nicht wäre für jede hilfe dankbar
miniC# - Mi 07.01.09 17:39
hm woher hast du das beispiel ? ich habe noch nie etwas von einer workerclass gelesen. auch mdsn spuckt dazu nichts bezüglich der hauseigenen frameworks aus. fehlt da eventuell code ?
ps : net zu ernst nehmen , hab keine ahnung :)
gruß,
miniC#
jaenicke - Mi 07.01.09 17:52
miniC# hat folgendes geschrieben : |
hm woher hast du das beispiel ? ich habe noch nie etwas von einer workerclass gelesen. auch mdsn spuckt dazu nichts bezüglich der hauseigenen frameworks aus. fehlt da eventuell code ? |
;-)
Darauf bezog sich das vor dem Code nämlich:
nellyville hat folgendes geschrieben : |
Hier noch der sourcecode vom WinFormThreading [...] |
;-)
nellyville - Mi 07.01.09 17:54
Leute wieder mal typish mein Lehrmeister wir sind hingesessen und haben versucht das ganze zu programmieren doch er selber brachte es auch nicht hin. Also bekam ich den neuen auftrag ein Timer zu schreiben welches nur 1 enen timer hat und mit einem backgroundworker funktioniert. Das immmer +1 pro sekunde raufgezählt wird ist der neue auftrag..
Ich danke euch für die Hilfe ;)
PS : falls ihr noch irgendwelche vorschläge habt wegem backgroundworker bin ich ganz Ohr :D
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!