Szukaj na tym blogu

czwartek, 16 września 2010

Sekwencja wywołań w asynchronicznym środowisku Silverlight cz. 1

Przes ostatnie kilka dni męczyłem się niemiłosiernie z asynchronicznością Silverlighta. Pomimo wielkiego entuzjazmu jaki żywię do tej technologii, pojawiły się we mnie pierwsze wątpliwości. Zacząłem się zastanawiać czy, aby na pewno Silverlight nadaje się do biznesowych rozwiązań czy też obiekt Session z XPO DevExpressa (ORM firmy DevExpress) jest w pełni dopracowany do wymagań jakie stawia Silverlight. A może to ja jestem w tym wszystkim najsłabszym ogniwem ? To ostatnie jest wielce prawdopodobne. Dosyć tego bajdużenia.

O co w tym wszystkim chodzi?

Jeśli Twój proces biznesowy wymaga byś odczytał obiekt ze źródła danych, a następnie wykorzystał informacje w nim zawarte do odczytania kolejnych danych, będziesz potrzebował sekwencyjnych wywołań asynchronicznych.
Rozwiązanie tego typu (metoda Initialize()):

public class Sample
{
    private FirstObject firstObj;
    private SecondObject secondObj;
 
    public void GetFirstObjectAsync(int id)
    {
        var service = new DummyWebService.ServiceSoapClient();
        service.GetFirstObjectCompleted += (sender, e) =>
        {
            firstObj = new FirstObject
                           {
                                Id = e.Result.Id,
                                ChildId = e.Result.ChildId
                           };
        };
        service.GetFirstObjectAsync(id);
    }
 
    public void GetSecondObjectAsync(int id)
    {
        var service = new DummyWebService.ServiceSoapClient();
        service.GetSecondObjectCompleted += (sender, e) =>
        {
            secondObj = new SecondObject
            {
                Id = e.Result.Id,
            };
        };
        service.GetSecondObjectAsync(id);
    }
 
    public void Initialize()
    {
        GetFirstObjectAsync(1);
        GetSecondObjectAsync(firstObj.Id);
    }
}


nie zda egzaminu ponieważ metody są wykonywane asynchronicznie co oznacza, że nie wiesz, która z nich wykona się pierwsza. W naszym przypadku wymogiem jest by najpierw wykonała się metoda GetFirstObjectAsync(1), a po otrzymania rezultatu, wykonała się metoda GetSecondObjectAsync(firstObj.Id).
Wywołanie tego w synchroniczny sposób spowoduje zablokowanie aplikacji.

Najprostszym rozwiązaniem jest coś takiego:


public class Sample
{
    private FirstObject firstObj;
    private SecondObject secondObj;
 
    public void GetFirstObjectAsync(int id)
    {
        var service = new DummyWebService.ServiceSoapClient();
        service.GetFirstObjectCompleted += (sender, e) =>
        {
            firstObj = new FirstObject
                           {
                                Id = e.Result.Id,
                                ChildId = e.Result.ChildId
                           };
                           GetSecondObjectAsync(firstObj.Id);
        };
        service.GetFirstObjectAsync(id);
    }
 
    public void GetSecondObjectAsync(int id)
    {
        var service = new DummyWebService.ServiceSoapClient();
        service.GetSecondObjectCompleted += (sender, e) =>
        {
            secondObj = new SecondObject
            {
                Id = e.Result.Id,
            };
        };
        service.GetSecondObjectAsync(id);
    }
 
    public void Initialize()
    {
        GetFirstObjectAsync(1);
    }
}


W ten sposób osiągniemy zamierzony efekt.
Problem pojawia się w momencie jak takich metod jest więcej. Zarządzanie takim kodem pozostawia wiele do życzenia – blah :/ ).

UWAGA:
Próba wywoływania asynchronicznie metody, wykorzystując delegata oraz jego metodę BeginInvoke() w Silverlight zakończy się wystąpieniem wyjątku NotSupportedException. Nazwa wyjątku mówi sama za siebie.

W kolejnej części postaram się pokazać jak wykonywać sekwencyjnie metody asynchroniczne przy wykorzystaniu corutines (http://pl.wikipedia.org/wiki/Wsp%C3%B3%C5%82program).

Brak komentarzy:

Prześlij komentarz