Benytter man HTTP stacken fra Silverlight – herunder kald af WCF services over HTTP – sker kaldet asynkront.  Derfor skal man passe på, hvis man opdaterer brugerkontroller i sin callback funktion, da den kan blive kaldt på en anden tråd end den, der ejer brugerkontrollen.  Det er gamle nyheder.  Bruger man et pattern som f.eks. MVVM, hvor opdatering af ens view sker gennem binding til properties på en viewmodel, sker marshalling til UI tråden automatisk af Silverlight’s binding mekanisme.  I andre tilfælde er man nødt til selv at sørge for, at brugerinterfacet opdateres på den rigtige tråd f.eks. gennem Dispatcher.

Jeg har først fornylig opdaget, at callbacks fra WCF services i nogle tilfælde automatisk bliver flyttet til den kaldende tråd i Silverlight.  Det gælder også Silverlight til WP7.  Det sker i det tilfælde, hvor man benytter client proxy klasserne, der genereres, når man vælger “Add service reference” fra Visual Studio. 

Lad os sige, at jeg har en service kaldet Service1 med en metode DoWork.  Jeg har tilføjet en reference til servicen gennem VS, hvorved et namespace ServiceReference1 med en proxy klasse kaldet Service1Client er blevet oprettet.  Følgende kode er dermed fuldt lovlig:

label1.Text = Thread.CurrentThread.ManagedThreadId.ToString();

ServiceReference1.Service1Client service = new ServiceReference1.Service1Client();
service.DoWorkCompleted += (s, args) =>
    {
        // Dette kald er fuldt lovligt, og label1 og label2 vil vise samme thread id.
        label2.Text = Thread.CurrentThread.ManagedThreadId.ToString();
    };
service.DoWorkAsync();

Kigger man dybt nok i de genererede klasser, kan man se, at de klassen AsyncOperation benyttes til at flytte kaldet tilbage til den kaldende tråd.  Har man brug for at lave noget arbejde i sin callback fra sin service, må man undlade at bruge den genererede client proxy og f.eks. bruge ChannelFactory eller noget andet.  Forrige eksempel er funktionelt ækvivalent med nedenstående, hvor marshalling til UI tråden sker manuelt gennem brug af AsyncOperation.  Bemærk at AsyncOperation skal oprettes gennem AsyncOperationManager.CreateOperation:

AsyncOperation asyncOp;

void CallWcf()
{
    asyncOp = AsyncOperationManager.CreateOperation(1);
    ServiceReference1.IService1Channel channel 
        = new ChannelFactory<ServiceReference1.IService1Channel>("BasicHttpBinding_IService1")
        .CreateChannel();
    channel.BeginDoWork(DoWorkCallback, channel);
}

void DoWorkCallback(IAsyncResult result)
{
    ServiceReference1.IService1Channel channel = result.AsyncState as ServiceReference1.IService1Channel;
    channel.EndDoWork(result);

    asyncOp.PostOperationCompleted(new SendOrPostCallback(o =>
        {
            label2.Text = (string) o;
        }), Thread.CurrentThread.ManagedThreadId.ToString());
}

I stedet for AsyncOperation kunne man også vælge at bruge SynchronizationContext eller Dispatcher direkte.  Faktisk er AsyncOperation blot en wrapper omkring SynchronizationContext, og i Silverlight er SynchronizationContext en instans af DispatcherSynchronizationContext, som igen er en wrapper omkring Dispatcher.  Så Dispatcher er den rigtige helt her.

Som jeg har nævnt før, og som alle nok efterhånden har hørt, så kan WP7 ikke synkroniseres med Outlook.  Det kom som lidt af en overraskelse for mig.  Jeg havde helt klart en forventning om, at Zune ville kunne synkronisere Outlook.  Efter det første chok havde lagt sig, begyndte jeg naturligvis at søge efter andre metoder.

WP7 synkroniserer helt perfekt med OWA, Windows Live og GMail.  Min første tanke var derfor at bruge firmaets OWA.  Desværre arbejder jeg i et firma, hvor OWA er et fy-ord, og man skal gennem VPN, Citrix og alt muligt, for at komme i nærheden af sin mailbox.

Næste bud på listen var Windows Live.  Mærkeligt nok var jeg ikke i stand til finde en mulighed for at synkronisere Outlook til Windows Live.  Der er mulighed for at få sin Windows Live kalender vist i Outlook, men det er den forkerte vej.  Hvis nogen kender en måde at synkronisere mellem Outlook og Windows Live, så lad mig endelig høre.

Sidste mulighed var GMail.  Google har deres egen Google Calendar Sync.  Desværre kunne jeg ikke få den til at virke overhovedet.  Den kom med en underlig fejl, og jeg har Google mistænkt for at have skrinlagt komponenten.  Ærgerligt.  Efter noget søgen faldt jeg over Ogg Sync.  Ogg Sync kan ifølge eget udsagn synkronisere både kalender og kontakter, hvilket var, hvad jeg havde brug for.  Jeg købte Ogg Sync (for $30 tror jeg), og synkronisering af Outlook kalender med GMail fungerede perfekt.  Men desværre kan man ikke bruge samme licens til synkronisering af kalender og kontakter.  Om det er en bug i Ogg Sync vides ikke, for support svarer ikke på mails, og der er intet nævnt på web sitet.  Så pas på med Ogg Sync!

Efter lidt mere søgning fandt jeg GO Contact Sync Mod, som kan synkronisere Outlook kontakter med GMail.  Det fungerer næsten perfekt.  Der er dog nogle problemer med at synkronisere kontakter, som bare har et firmanavn.  Men det er småting.

Efter møge og besvær, begyndte Google Calendar Sync på magisk vis også at virke, så Ogg Sync er sendt på pension, og jeg er endt med følgende setup:

  • Google Calendar Sync til at synkronisere kalender med GMail.
  • GO Contact Sync Mod til at synkronisere kontakter med GMail.

Det er lidt noget rod at skulle have flere “services” kørende bare for at kunne synkronisere.  Men der er også fordele ved, at Zune ikke kan synkronisere på desktoppen.  Sålænge min computer bare er tændt på arbejdet, vil Exchange på arbejdet være opdateret med de aftaler, jeg ligger ind i min WP7 – og omvendt.  Det er faktisk genialt, og nu hvor det bare spiller, synes jeg klart det er en bedre løsning en synkronisering med Outlook. 

Samtidig er min WP7 synkroniseret med en OWA fra mit eget firma.  I WP7’s kalender bliver aftaler fra de forskellige kalendere vist med forskellige farver, så man har fuldstændig styr på det.

Er der andre, som har erfaringer med synkroniseringen, og som måske har en smartere løsning, så vil jeg gerne høre det.