dinsdag 27 januari 2009

Prism: Compact Framework en Asynchrone functies

Ik heb een kleine test gedaan om te kijken of je met Delphi Prism en het Compact Framework ook "async" blokken en "future" variabelen kunt gebruiken (voor parallelle c.q. asynchrone verwerking). Hiervoor maakte ik een klein test project (zie mijn vorige blog) met onder een knop de volgende (nutteloze) test code:
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
var i: future Integer;
var j: Integer;

i := async 1; //background asigning 1 to i, next line will wait
j := 2 + i; //j should be 3 now
end;
Prism compileert de code gewoon, alleen als ik tijdens het runnen op de bewuste test knop druk, krijg ik een foutmelding: FileLoadException System.Core.dll.
Ook in de emulator gaat het fout, en krijg ik dezelfde foutmelding. Tijd om even wat dingen uit te zoeken!

RemObjects (de makers van de Oxygene c.q. Prism compiler) heeft gelukkig een aantal nieuwsgroepen waar actief en snel reactie gegeven wordt:
Support page: http://www.remobjects.com/support.aspx
Newsgroup support: http://www.remobjects.com/page.aspx?id={C4764DFE-288D-4C17-90F8-FA5B7BFB3BCB}

Aangezien de PublicKeyToken belangrijk is bij het laden van assembly's, heb ik met .Net Reflector gekeken naar de references van mijn executable. Hierbij viel gelijk het probleem op:
Alle references wezen naar assembly's met PublicKeyToken=969db8053d3322ac, behalve "System.Core.dll", deze verwees naar b77a5c561934e089!
In de nieuwsgroep kreeg ik de tip om het project te compileren met de gratis command line compiler. En om met de hand mijn .oxygene bestand (=project file) aan te passen, zodat het de goede reference voor System.Core.dll zou gebruiken:


(op de een of andere manier lukt het niet om als tekst te doen: opmaak gaat fout bij XML...)

Vervolgens gecompileerd via de command line:
oxygene.exe -rebuild -frameworkfolder="C:\Program files\Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE"
En nu kan ik hem wel gewoon draaien en debuggen... alleen op de desktop... Helaas gaat het nog steeds fout in de emulator (harde crash zonder foutmelding).
Als je kijkt met Proces Explorer welke dlls hij op de desktop gebruikt, blijkt dat .Net altijd de volledige (niet de CF) System.Core.dll gebruikt: deze is wel aanwezig op de desktop, maar uiteraard niet in de emulator.

Als laatste poging heb ik via .Net Reflector met de FileGenerator plugin mijn assembly geëxporteerd naar C# code:
Het trouwens wel interessant om te kijken wat voor code automatisch gegenereerd wordt voor mijn paar regels code (de meeste code zit overigens in de "FutureHelper" class):
Vervolgens heb ik met C# Visual Studio Express een nieuw project aangemaakt (zie deze link voor VS Express en Compact Framework). Na wat aanpassingen compileerde het en kon ik het testen in de emulator. Deze geeft gelukkig wat meer informatie: op de volgende regel gaat het fout:
Func func = PrivateImplementationDetails.FutureHelper.ExecuteAsync(delegate {
return 1;
}, true);
Deze geeft de foutmelding:
NotSupportedException: .Net Compact Framework does not support invoking delegates asynchronously
Dus het Compact Framework ondersteunt deze functionaliteit gewoon niet! Dus einde oefening...

In ieder geval was het erg leerzaam (onder het motto: je leert het meest bij fouten). Waarschijnlijk zal CodeGear/RemObjects in de volgende versie een aantal kleine bugs die ik tegen kwam verhelpen. Misschien dat .Net CF versie 4 wel betere asynchrone ondersteuning heeft (dmv Parallel Extensions).

Geen opmerkingen: