De fleste som har programmeret Windows applikationer med et brugerinterface ved, at man ikke kan tilgå vinduer fra andre tråde end den tråd, der har oprettet vinduet, og som står for at pumpe beskedkøen til vinduet.
I klassisk Win32 er det ganske simpelt at overholde denne regel, da man med PostMessage nemt kan placere en besked i et vindues beskedkø, selvom man kalder fra en anden tråd. PostMessage returnerer øjeblikkeligt. SendMessage er en lidt anden historie. Såvidt jeg husker, bør man ikke kalde den fra en anden tråd, da man kan risikere, at man bliver blokeret i længere tid indtil tråden, der ejer vinduet, vågner op og får pumpet nogle beskeder. Hvis SendMessage kaldes fra den ejende tråd, bliver Windows proceduren kaldt direkte, hvilket effektivt svarer til at placere en besked forrest i beskedkøen og pumpe med det samme.
I .NET og WinForms benyttes Control.InvokeRequired, Control.Invoke og Control.BeginInvoke.
Jeg har altid tænkt på Control.Invoke som svarende til SendMessage og Control.BeginInvoke som svarende til PostMessage. I praksis passer det også meget godt, men det er ikke helt det samme der sker. Faktisk bliver PostMessage kaldt af både Invoke og BeginInvoke.
Når man benytter Invoke og BeginInvoke, registrerer WinForms en ny besked i Windows og benytter PostMessage til at anbringe beskeden i beskedkøen for vinduet (i Win32 er der i princippet ingen forskel på kontroller og vinduer – alt er vinduer). Forskellen på Invoke og BeginInvoke er, at Invoke venter indtil vinduets beskedkø har behandlet beskeden, mens BeginInvoke returnerer med det samme.
Resultatet er, at der for Invoke godt kan gå længere tid, inden funktionen returnerer, hvis der allerede ligger en milliard beskeder i køen, eller vinduet af den ene eller anden grund ikke lige pumper beskedkøen.
Medmindre man virkelig har brug for at vente, vil BeginInvoke derfor være at foretrække.