BeginInvoke Problem


realpk

Mitglied
Irgendwie funktioniert das ausführen als asynchroner Thread nicht mehr bei mir.
Weiss jemand was ich falsch gemacht habe.

public delegate void testdelegate();
public void testmethode()
{
System.Threading.Thread.Sleep(100000);
}

public void button1_Click(object sender, System.EventArgs e)
{
this.BeginInvoke( new testdelegate(testmethode));
}

Bei einem Klick auf den Button friert das Fenster ein.
 

broetchen

Erfahrenes Mitglied
moin

Ich kenn mich bei Threads nicht wirklich aus, aber hast du testmethode mit dem Delegaten verbunden?

mfg broetchen
 

realpk

Mitglied
Inwiefern verbunden? Ich erstelle bei BeginInvoke ja eine neue Instanze des Delgates mit bezug auf die Methode. Sorry weiss nicht wie ich das anders beschreiben soll.
 

Christian Kusmanow

Erfahrenes Mitglied
Weiss jemand was ich falsch gemacht habe.
Nein, ich weiss nicht mal was Du machen willst. :rolleyes:

Weisst Du denn überhaupt was genau schief gegangen ist? Schon mal was von Try-Catch gehört?

Schau dir mal die [thread=199136]Tutorials[/thread] im 2.Post an!

@Brötchen: Ist auch was für Dich! ;)
 

realpk

Mitglied
ich möchte das die testmethode in einem anderen Thread gestartet wird.
Es gibt keine Exception und somit bringt try-Catch leider auch nichts.
Die Methode wird zwar aufgerufen aber im selben Thread.
 

Caracho

Mitglied
Wenns nicht unbedingt BeginInvoke sein muss, dann lös das doch mit normalen Threads.

Code:
using System.Threading;

...

Thread t = new Thread(new ThreadStart(testmethode));
t.Start();
 

Caracho

Mitglied
Das mit einem Rückgabewert wird weder mit BeginInvoke noch mit "normalem" Threading funktionieren. Die Multithreading Programmierung ist nunmal ereignisgesteuert.
Das "normale" Programmiermodell mit Rückgabewert zieht hier nicht.
Du kannst jedoch Ereignisse definieren, welche bei Beendigung des Threads ausgeführt werden, und damit einen beliebigen Wert zum Ereignisempfänger transportieren.

Am Besten du siehst dir mal die Beispiele zum Thema Threading und Event-Handling in der MSDN an.
 

Caracho

Mitglied
Ja, schon klar. Aber das ist sicher nicht der Rückgabewert den du haben willst.

Das IAsyncResult-Objekt erhälst du ja noch vor der eigentlichen Ausführung,
also bevor im ThreadPool ein passender Thread dafür gestartet wurde.

Würdest du das IAsyncResult-Objekt erst nach der Ausführung des Threads
erhalten, dann hättest du nichts gewonnen, da du ja dann auf die Abarbeitung des Threads warten müsstest und somit der Multithreading-Vorteil weg wäre.

Das IAsyncResult-Objekt ist z.b. wichtig wenn du mit asynchronen Delegates arbeitest:

Code:
public delegate bool DummyDelegate(int i);

public bool Dummy(int i)
{
  return 10 % i == 0;
}

public void BeginDummy(int i)
{
 DummyDelegate dd = new DummyDelegate(Dummy);
 dd.BeginInvoke(i, new AsyncCallback(DummyCallback), dd);
}

private void DummyCallback(IAsyncResult ar)
{
 DummyDelegate dd = ar.AsyncState as DummyDelegate;

 // Hier ist der "Rückgabewert"
 bool ergebnis = dd.EndInvoke(ar);

 MessageBox.Show(ergebnis.ToString());
}
Das Beispiel macht natürlich jetzt den Multithreading Vorteil nicht deutlich,
aber es zeigt wie es gemacht werden könnte.
 

realpk

Mitglied
Ich frage mich einfach nur, was an meinem ja nicht wirklich umfangreichen Beispiel falsch ist. Es muss doch als neuer Thread abgearbeitet werden. Bzw in einem anderen wie das Control welches es aufruft (this)
 

Christian Kusmanow

Erfahrenes Mitglied
Na wenn Du jetzt dein erstes Beispiel meinst ist es so,
dass die Methode button1_Click in dem gleichen Thread ausgeführt wird in dem das Form ausgeführt wird (Main-Thread).
Somit wird das Thread.Sleep in der Methode testmethode nun auch nur in dem Main-Thread ausgeführt.

MfG, cosmo
 

realpk

Mitglied
Da steht doch:
"Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on"

Und das verstehe ich so das ein asynchrones Thread gestartet wird.
Und da ich von dem Form BeginInvoke aufrufe, doch asynchron zu dem Form
 

Alexander Schuc

crazy-weasel
Stell dir vor du hast 2 Threads.

Thread1, der StandardThread, hat die Controls erstellt.
In Thread2 läuft gerade irgendeine Methode, und dort rufst du BeginInvoke auf.
In Bezug zu Thread2 rennts asynchron, zu Thread1 aber nicht.

Rate mal wieviele Threads du hast. Genau, einen. Oder vielleicht hast irgendwo andere Threads, aber das Button-Event ist doch wohl ziemlich sicher im Thread der Controls.
 

realpk

Mitglied
Es wird doch alles nacheinnander abgearbeit.
Die Controls werden erstellt und dann der rest...
Wenn ich jetzt den Button klicke läuft das doch im selben Thread wie die Controls.
Sollte zB. eine Methode länger brauchen wird ja auf die Events auch nicht reagiert.
Jetzt rufe ich das BeginInvoke aus diesem einen Thread auf.
Nun sollte doch dafür ein neuer Thread aufgemacht werden. Asynchron zu den Controls, der Events und dem sonstigen Ablauf.

Irgendwie will mir das nicht so richtig in den Kopf was du genau meinst.
Solange ich "manuell" keinen neuen Thread "erstelle" läuft doch alles in einem Thread und somit ist der 2te asynchron zu dem ersten.

Bitte erläutere was ich daran falsch sehe.
Schonmal vielen Dank im Vorraus.
 

Alexander Schuc

crazy-weasel
BeginInvoke erzeugt keinen neuen Thread.

Das ist das was du falsch verstehst.

Schau dir mal den Code am Ende des Postings an.

Wenn 'newThread' aufgerufen wird, erzeugen wir einen neuen Thread der die Methode 'SleepWell' ausführt.
'SleepWell' wird ein wenig schlafen, und dann mittels BeginInvoke die Methode 'aMethod' aufrufen.

Die Situation ist nun folgende:
  1. Wir haben 2 Threads. Einen Haupthread, und einen von uns erzeugten Nebenthread.
  2. Im Nebenthread wird BeginInvoke vom Formular aufgerufen

Das Resultat ist, 'aMethod' wird im Hauptthread abgearbeitet, obwohl das Programmstück wo die Methode über den Delegate aufgerufen wird im Nebenthread läuft.
Würden wir das BeginInvoke und den Delegate weglassen, also direkt 'aMethod' aufrufen würde die Methode im Nebenthread laufen.

Weil du dich vielleicht nun wieder fragst was da nun Asyncron ist, beim Aufruf über BeginInvoke wird nicht gewartet, bis die Methode fertig ausgeführt wurde.

Code:
public delegate void TestDelegate();

private void newThread()
{
	Thread t = new Thread(new ThreadStart(SleepWell));
	t.Start();
}

private void SleepWell()
{
	Thread.Sleep(100000);
	this.BeginInvoke(new TestDelegate(aMethod));
}

private void aMethod()
{
}