Archiv für 6. Mai 2010

Nach dem ich meinen vorherigen Artikel zum Thema “Asynchrone Kommunikation mit dem Async-Pattern” vorgestellt hatte, hat Ralf Westphal auf seinem Blog “One Man Think Tank Gedanken” das Vorgehen zur Implementierung einer asynchronen Kommunikation mit Hilfe von Event-Based-Components vorgestellt, welches eine sehr gute Alternative zum Async-Pattern ist. Seinen Eintrag nehme ich zum Anlass, um meine Beispiel-Implementierung des Async-Pattern zu refaktorisieren, um eine bessere Trennung der Verantwortlichkeiten und somit eine bessere Lesbarkeit zu erreichen.

In das Form wird die Abhängigkeit “CalcProxy” injected.

static void Main()

{

    CalcProxy calcProxy = new CalcProxy(new Calculator());

    Application.EnableVisualStyles();

    Application.SetCompatibleTextRenderingDefault(false);

    Application.Run(new Form1(calcProxy));

}

 

Im Gegensatz zur vorherigen Version wird in der Form nun nicht mehr der Calculator direkt erzeugt und verwendet, sondern auf den injekteten CalcProxy zugegriffen.

public partial class Form1 : Form {

    private readonly ICalcProxy m_calcProxy;

    public Form1(ICalcProxy calcProxy) {

        InitializeComponent();

        m_calcProxy = calcProxy;

        m_calcProxy.CalcCompleted += CalculatorCalcCompleted;

    }

 

    private void Run_Click(object sender, EventArgs e) {

        int number;

        if (Int32.TryParse(txbEingabe.Text, out number)) {

            m_calcProxy.CalcAsync(number, number);

        }

    }

 

    void CalculatorCalcCompleted(object sender, CalcEventArgs eventArgs) {

        lblCounter.Text = eventArgs.UserState.ToString();

    }

}

 

Der CalcProxy wiederum bekommt die Abhängigkeit zum Calculator injected und stellt für die Calculator.Calc-Methode sowohl eine synchrone als auch eine asynchrone Methode zur Verfügung.

public class CalcProxy : ICalcProxy {

    private readonly ICalculator m_calculator;

    public event CalcCompletedEventHandler CalcCompleted;

    private AsyncOperation m_asyncOperation;

    private bool m_isRunning;

 

    public CalcProxy(ICalculator calculator) {

        m_calculator = calculator;

    }

 

    public int Calc(int number) {

        return m_calculator.Calc(number);

    }

 

    public void CalcAsync(int number, object userState) {

        lock (this) {

            if (m_isRunning) {

                throw new InvalidOperationException("Diese Operation wird bereits ausgeführt");

            }

            m_isRunning = true;

            m_asyncOperation = AsyncOperationManager.CreateOperation(userState);

            ThreadPool.QueueUserWorkItem(ExecuteCalc, number);

        }

    }

 

    private void ExecuteCalc(object state) {

        var result = Calc((int)state);

        m_asyncOperation.PostOperationCompleted(CalcCompletedSuccessful, result);

    }

 

    private void CalcCompletedSuccessful(object result) {

        if (CalcCompleted != null) {

            CalcCompleted(this, new CalcEventArgs(null, false, (int)result, result));

        }

    }

}

 

Nun enthält der Calculator nur noch die Methode die für den Calculator notwendig ist, nämlich die Calc-Methode.

public class Calculator : ICalculator {

    public int Calc(int number) {

        Thread.Sleep(10000);

        return number * number;

    }

}

kick it on dotnet-kicks.de

Share

Comments 4 Kommentare »