Welcher C#-/.NET-Entwickler kennt es nicht? Die Anwendung bzw. das UI hängt während einer länger dauernden Prozedur und wurde daher in einen eigenen Thread ausgelagert.
Status Updates an das UI müssen dann entsprechend ge-dispatched werden. Je nach Code Komplexität weiß man jedoch manchmal nicht, in welchem Thread man sich befindet und ob die Aktualisierung im UI nun mittels Dispatcher erfolgen muss.

Eine schnelle Prüfung mittels Application.Current.Dispatcher.CheckAccess() gibt Auskunft darüber. Schnell entsteht solcher Code:

if (Application.Current.Dispatcher.CheckAccess())
{
    tbResultState.Text = "Ready!";
    btnStart.IsEnabled = true;
    lbStatus.Content = "It's ready to start over";
    // etc etc
}
else
{
    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
        {
            tbResultState.Text = "Ready!";
            btnStart.IsEnabled = true;
            lbStatus.Content = "It's ready to start over";
            // etc etc
        }));
}

Die Aktualisierungen für den UI Thread müssen oft zweifach geschrieben werden. Einmal in einem Lambda Ausdruck und einmal normal falls der Zugriff auf das UI möglich ist.
Einfach immer den Dispatcher zu verwenden kann je nach Architektur zu Performance Problemen führen, daher ist dies auch keine Lösung.

Betrachten wir einmal einen kleinen Wrapper um den Dispatcher herum. Der Aufruf könnte so aussehen.

MyDispatcher.Dispatch(() =>
        {
            tbResultState.Text = "Ready!";
            btnStart.IsEnabled = true;
            lbStatus.Content = "It's ready to start over";
            // etc etc
        });

Der eigenen Dispatcher Klasse, bzw. dem Wrapper um den Dispatcher der Application wird einfach der Code der im UI ausgeführt werden soll/muss als simpler Lambda Ausdruck übergeben.
Die Logik der MyDispatcher.Dispatch() Methode entscheidet anschließend ob der Code ausgeführt oder an den Dispatcher der Anwendung delegiert werden muss.

Betrachten wir die innere Logik der MyDispatcher Klasse:

public class MyDispatcher
{
    public delegate void DispatchDelegate();

    private static Dispatcher ApplicationDispatcher = Application.Current.Dispatcher;
    public static void Dispatch(DispatchDelegate ActionMethod)
    {
        if (ApplicationDispatcher.CheckAccess())
        {
            ActionMethod();
        }
        else
        {
            ApplicationDispatcher.BeginInvoke(new Action(ActionMethod));
        }

    }
}
Categories: CSharp

0 Comments

Leave a Reply