Verfasst von: bletra | 1. Februar 2011

Delegates (Teil 5 von 6): Asynchrone Delegate

Die Artikelreihe nähert sich langsam dem Ende. Bisher habe ich folgende Themen behandelt:

Asynchrone Programmierung ist ein schwer abzugrenzendes Thema.

In Bezug auf Delegates fangen wir mit einem einfachen Beispiel an: Während im Hintergrund beispielsweise die Festplatte durchsucht wird, läuft das Hauptprogramm weiter. An einer fest gelegten Stelle im Hauptprogramm wird das Ergebnis der Suche verarbeitet. Entweder die Suche ist dann schon abgeschlossen, oder das Programm wartet nun, bis dies geschehen ist (Zeile 32). Wir definieren also wieder ein Delegate (Zeile 1), instanziieren es mit einer der Signatur entsprechenden Methode (Zeile 24) und mit BeginInvoke (Zeile 25) leiten wir den asynchronen Aufruf ein. Mit EndInvoke (Zeile 32) warten wir auf sein Ende. Danach können wir den Rückgabewert (die Liste der gefundenen Dateien) verarbeiten.

delegate List LongProcessCaller(string name);
public class Test
{
  public List Search(string path)
  {
     List result = new List();
     Console.WriteLine("async: start long search process in " + path);
     for (int i = 0; i < 2; i++)
     {
       System.Threading.Thread.Sleep(50);
       result.Add("filename " + i.ToString());
       Console.WriteLine("async: found one file");
     }
     Console.WriteLine("async: finnished long search process...");
     return result;
  }
}
class Program
{
  static void Main(string[] args)
  {
    Test t = new Test();
    Console.WriteLine("Hello this is the main program, ...");
    LongProcessCaller caller = new LongProcessCaller(t.Search);
    IAsyncResult result = caller.BeginInvoke(@"c:\tmp", null, null);
    for (int i = 0; i < 3; i++)
    {
      Console.WriteLine("main:I work too ...");
      System.Threading.Thread.Sleep(25);
    }
    Console.WriteLine("main: wait for long process to finnish");
    List found = caller.EndInvoke(result);
    Console.WriteLine("main:found the following items: ");
    foreach (string filename in found)
      Console.WriteLine(filename);
   Console.ReadLine();
 }
}

Jetzt wartet das Programm zwar nicht direkt beim Aufruf der Routine, aber doch ggf. später. Schöner wäre es, wenn die Verarbeitung des Ergebnisses der Suche dann erfolgen könnte, wenn die Suche beendet ist.
Dies ist durch Übergabe einer Methode bei BeginInvoke (Zeile 26) möglich:

//restlicher Code wie oben
IAsyncResult result = caller.BeginInvoke(@"c:\tmp", new AsyncCallback(MyCallback), null);
//...EndInvoke nicht hier!
static void MyCallback(IAsyncResult async)
{
  System.Runtime.Remoting.Messaging.AsyncResult ar = (System.Runtime.Remoting.Messaging.AsyncResult) async;
  LongProcessCaller caller = (LongProcessCaller)ar.AsyncDelegate;
  List found = caller.EndInvoke(async);
  Console.WriteLine("callback:found the following items: ");
  foreach (string filename in found)
    Console.WriteLine(filename);
}

Um an das eigentliche Ergebnis zu kommen, muss man trickreich casten, aber die Codezeilen lassen sich leicht auf andere Probleme übertragen.

Auf diese Art und Weise ließen sich viele Hintergrundarbeiten gleichzeitig starten:

for (int i = 0; i < 50; i++)
{
  IAsyncResult result = caller.BeginInvoke(i.ToString(), new AsyncCallback(MyCallback), null);
}

Mit BeginInvoke wird ein Thread im ThreadPool gestartet. Die Anzahl der möglichen Threads im Threadpool ist beschränkt, ggf. landet ein Thread dann in der Warteschlange.

Dieser Artikel ist nur ein sehr kurzer Einstieg in die asynchrone Programmierung und ich beschränke mich in dieser Stelle auch nur auf die einfache und direkte Möglichkeit, die Delegate bieten. Mit der neuen .Net-Sprache F# oder den Task-Klassen bieten sich viel mehr Möglichkeiten.
Mehr zu asynchroner oder paralleler Programmierung (hier tut sich gerade im .Net-Umfeld sehr viel) finden Sie hier:

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

Kategorien

%d Bloggern gefällt das: