PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C#] Frage zu Threads


minos5000
2008-07-29, 18:14:49
Hi,

ich bin gerade dabei mein erstes Programm unter C# zu schreiben, um genau zu sein verwende ich das Compact Framework, da es auf einem Windows Mobile Gerät laufen soll.

Momentan versuche ich einen Thread einzubauen, so dass in regelmäßigen Abstanden eine bestimmte Methode aufgerufen wird, aber das ganze funktioniert noch nicht so wie gewünscht.

Der Code sieht folgendermaßen aus:

public partial class Form1 : Form
{
Thread trd;

private void startMonitoring()
{
trd = new Thread(new ThreadStart(doSomething));
trd.Start();
}

private void doSomething()
{
while(true)
{
printSignalStrength();
Thread.Sleep(5000000);
}
}

private void printSignalStrength()
{
...
}

public Form1()
{
InitializeComponent();
}

private void exitItem_Click(object sender, EventArgs e)
{
Application.Exit();
}

private void menuItem1_Click(object sender, EventArgs e)
{
startMonitoring();
}
}


In "printSignalStrength()" wird die aktuelle Signalsträke ausgelesen und an eine TexBox angehängt.

Wenn ich diese Methode manuell, d.h. z.B. per Button aufrufe, wird die die Signalstärke auch korrekt angezeigt, aber seit ich die Threadlogik hinzugefügt habe hängt sich das Programm beim Aufruf von "startMonitoring()" jedesmal auf, so dass ich es von Hand abschießen muss, und ausgegeben wird natürlich auch nichts.

Woran liegt das?? Habe ich beim einbauen des Threads etwas übersehen?



vg
minos


EDIT
Btw, es sieht so aus, als ob printSignalStrength niemals aufgerufen wird. Ich hab ein paar Zeilen als Log eingefügt und diese werden nie ausgegeben. D.h. es sieht aus, als hätte

trd = new Thread(new ThreadStart(printSignalStrength));

überhaupt keine Wirkung...

Gast
2008-07-29, 18:55:43
Ich vermute, du hast nur im UI-Thread Zugriff auf die Textbox. Da printSignalStrength jedoch nicht im UI-Thread läuft, geht das so nicht.
Glaube, du müsstest in doSometing() die Invoke-Methode deines Forms aufrufen und ein delegate auf printSignalstrength() übergeben.

ESAD
2008-07-29, 18:56:49
du möchtest also von einem thread auf das GUI zugreifen?

edit: da war schon wer schneller

minos5000
2008-07-29, 19:12:13
Danke für die Info, kennt ihr evtl. ein Beispiel wo das Vorgehen diesbezüglich erklärt wird?

Gast
2008-07-29, 20:02:52
Füg oben eine neue Definition ein:
private delegate void SimpleCallback();

und dann in doSomething:
this.Invoke(new SimpleCallback(printSignalStrength));
anstelle von: printSignalStrength();

übrigens ist dein Thread.sleep 5000 Sekunden lang, weiss nicht ob das so beabsichtigt ist.

minos5000
2008-07-29, 22:27:20
übrigens ist dein Thread.sleep 5000 Sekunden lang, weiss nicht ob das so beabsichtigt ist.

Danke für den Hinweis. Ich war irgendwie noch auf Mikrosekunden aus meinem vorherigen Projekt gepolt :rolleyes:

minos5000
2008-07-30, 09:15:20
Noch ein kleines Problem, ich hab die von dir vorgeschlagenen Änderungen übernommen und der Thread wird jetzt auch erfolgreich gestartet und erledigt seinen Job.

Aber immer wenn ich die Anwendung über den Exit-Button wieder beenden will schmiert sie mir schon wieder ab, d.h. der Thread stellt seine Arbeit ein, aber die Anwendung beendet sich nicht. Wie kann denn so etwas passieren?

Monger
2008-07-30, 10:01:00
Im Standardframework verwendet man für solche Aufgaben die Windows.Forms.Timer Klasse (http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx) - eben weil der Zugriff auf die GUI nicht ganz unproblematisch ist. Und laut Dokumentation sollte es diese Klasse im Compact Framework auch geben. Den solltest du auch im Oberflächeneditor in der Toolbox wiederfinden.

Und vorallem ist ein "Sleep" äußerst unzuverlässig. Je nach Rechenauslastung kann dieses Sleep auch länger dauern als erwartet - für einen regelmäßigen Zeitrhythmus ist sowas ungeeignet.

minos5000
2008-07-30, 11:32:18
Super, mit dem Timer haut jetzt alles hin. Ich war zuerst etwas verwirrt, weil seltsamerweise die Timer.Start() Methode nicht zur Verfügung steht. Aber ein myTimer.Enabled = true hat auch geholfen.

Gast
2008-07-30, 12:09:58
Der normale Windows Forms Timer hat doch aber auch eine Start() Methode |:

Monger
2008-07-30, 12:15:51
Der normale Windows Forms Timer hat doch aber auch eine Start() Methode |:
... aber kurioserweise nicht im Compact Framework!

Weiß der Kuckuck warum, aber ausgerechnet diese Methode existiert dort tatsächlich nicht.

Gast
2008-07-30, 14:03:15
... aber kurioserweise nicht im Compact Framework!

Weiß der Kuckuck warum, aber ausgerechnet diese Methode existiert dort tatsächlich nicht.
"wegoptimiert" um platz zu sparen? ich mein mehr als enabled auf true zu setzen macht die methode ja auch nicht.

Coda
2008-07-30, 14:56:44
Ich habe dunkel in Erinnerung dass man auf die GUI ausschließlich mit dem Hauptthrread zugreifen darf.

Monger
2008-07-30, 15:22:11
Ich habe dunkel in Erinnerung dass man auf die GUI ausschließlich mit dem Hauptthrread zugreifen darf.
Das ist richtig, allerdings kann man über "invoke" und noch ein paar andere Wege dem Event Handler Thread noch ein paar Methoden zuschieben.

Ist aber hässlich, und sollte so weit es nur irgendwie geht verhindert werden. Dafür gibt es dann Objekte wie den BackgroundWorker oder den Timer, die ein Stück weit die Kommunikation zur Oberfläche aus einem fremden Thread heraus organisieren können.