Asynchrone Aufrufe

Asynchrone Aufrufe

Wann immer eine Anwendung langwierige Aufgaben durchführen muss, ist es notwendig sich Gedanken darüber zu machen, wie man diese Prozesse parallel durchführt ohne die eigentliche Benutzerschnittstelle zu blockieren.
Stellen wir uns beispielsweise vor, eine Anwendung soll eine komplexe Berechnung durchführen und die Benutzeroberfläche dabei nicht blockieren.
Diese Aufgabe könnte man nun super in einem asynchronen Aufruf durchführen.
Im folgenden Beispiel werde ich dazu ein delegate erstellen und dieses mit BeginInvoke aufrufen.
Sobald die Methode fertig ist, wird ein Callback aufgerufen in dem wir dem Benutzer die Ergebnisse ausgeben können.

Nehmen wir mal folgendes Beispiel:
class AsyncProcess
{
    private delegate int ProcessDelegate(int count);

    public void Start()
    {
        ProcessDelegate del = new ProcessDelegate(ProcessWorker);
        del.BeginInvoke(100, new AsyncCallback(ProcessCallback), del);
    }

    private int ProcessWorker(int count)
    {
        Console.WriteLine("Asynchroner Vorgang wird gestartet..");

        int result = 0;
        for (int i = 0; i < count; i++)
        {
            Console.Write("1.");

            result += i;
            Thread.Sleep(10);
        }

        return result;
    }

    private void ProcessCallback(IAsyncResult ar)
    {
        ProcessDelegate del = (ProcessDelegate)ar.AsyncState;
        int result = del.EndInvoke(ar);

        Console.WriteLine();
        Console.WriteLine("Asynchroner Vorgang wurde beendet, das Ergebnis ist {0}.", result);
    }

    static void Main()
    {
        AsyncProcess asyncProcess = new AsyncProcess();
        asyncProcess.Start();

        Console.WriteLine("Normaler Vorgang wird gestartet..");

        for (int i = 0; i < 10; i++)
        {
            Console.Write("2.");
            Thread.Sleep(10);
        }

        Console.WriteLine();
        Console.WriteLine("Normaler Vorgang wurde beendet.");

        Console.ReadKey(false);
    }
}

Der Code erzeugt folgende Ausgabe:


Wie ihr sehen könnt, wird der 1. Vorgang parallel zum laufenden 2. Vorgang ausgeführt, d.h. die Berechnung läuft im Hintergrund und die Programmausführung wird nicht unterbrochen.

In der Main-Methode erstellen wir eine Instanz von AsyncProcess und starten die darin enthaltene Methode Start.
Diese Methode erzeugt ein delegate, dass auf die Methode ProcessWorker zeigt und startet diese Methode mit BeginInvoke asynchron.
Die Methode führt nun eine Berechnung durch und sobald diese abgeschlossen ist, wird das Callback ProcessCallback aufgerufen.
Da ich bei BeginInvoke im letzten Parameter den delgate übergeben habe, kann ich nun hier über den Parameter vom Typ IAsyncResult.AsyncState den delegate ermiteln und damit wiederum über EndInvoke das Ergebnis herleiten.
Der Trick ist also, einfach bei BeginInvoke das eigentliche delegate zu übergeben, um im Callback darauf zuzugreifen und über EndInvoke den Rückgabewert zu ermiteln.
Um einen Kommentar zu hinterlassen, ist eine Anmeldung erforderlich.