Dispatcher.SwitchTo()

03/08/2015 3 commentaires

Thread, SynchronizationContext et autres mécanismes asynchrones mis sur le devant de la scène des interfaces fluides et réactives restent des objets complexes aux fonctionnement souvent mal compris.

Depuis C# 5, les choses se simplifient incroyablement au niveau de la syntaxe, le code apparaissant quasiment comme synchrone.

J’ai souvent traité de ce sujet passionnant, comme lors du Techdays 2014. J’y avais notamment détaillé le rôle des Awaiters qui sont à la base des mécanismes de continuation de code (await).

Pas de classe de base ni d’interface pour prétendre pouvoir être “awaité” mais uniquement une convention: implémenter une méthode publique GetAwaiter() retournant un objet implémentant l’interface INotifyCompletion

Les classes Task et TaskAwaiter du framework .Net offre une version prête à l’emploi de ces mécanismes et pour le commun des développeurs, apprendre à appréhender la classe Task sera largement suffisant pour implémenter un maximum de scénarios asynchrones.

Pour autant, certaines tâches plus complexes ou demandant une maitrise plus fine nécessiteront tout de même la mise en œuvre de nos propres Awaiters.

Je vous propose donc de faire quelques rappels ici avant de démontrer une solution plus complexe dans un billet ultérieur.

Pour rappel, c’est un exemple que j’avais présenté lors de la session des Techdays 2014 “C# Async, un après” : https://www.youtube.com/watch?v=M8ypKMorCsU

Ainsi pour pouvoir utiliser le mot clé “await”, il faut le faire suivre d’un objet exposant une méthode GetAwaiter(). Finesse extrême du compilateur C#, cette méthode peut être une méthode d’extension ! Ceci est très bien vu car on peut donc rendre “awaitable” d’anciennes classes ou des classes dont nous n’aurions pas les sources.

public static class AsyncExtensions
{
    public static TaskAwaiter GetAwaiter(this Int32 millisecond)
    {
        return Task.Delay(millisecond).GetAwaiter();
    }
    public static TaskAwaiter GetAwaiter(this DateTime time)
    {
        return Task.Delay((int)(time - DateTime.Now).TotalMilliseconds).GetAwaiter();
    }
}

Le code ci-dessus nous montre comment rendre le type “int” et “datetime” awaitables.

Nous leur ajoutons par extension une méthode “GetAwaiter” qui sera correctement résolue par le compilateur C# lorsqu’elle sera combinée à un await.

Vous remarquerez que dans cet exemple, je ne redéveloppe pas mon propre Awaiter mais je combine l’awaiter de Task.Delay().

Je peux désormais appeler les codes suivants qui sont équivalents :

await Task.Delay(1000);
await 1000;
await (DateTime.Now + TimeSpan.FromMilliseconds(1000));


La suite concerne WPF mais peut-être imaginée dans d’autres contextes de synchronisation de threads.

Dans le code suivant, une majorité de développeurs connaissent le problème, il n’est pas possible d’accéder à un élément graphique de WPF depuis un thread autre que le thread de rendu: ici l’accès à la propriété Title de la fenêtre depuis un thread du pool soulèvera une exception.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Task.Run(() =>
        {
            Title = "ok";
        });
    }
}

Dans WPF, le contexte d’exécution relatif à une fenêtre est simplifié au travers d’une classe appelée Dispatcher, nul besoin donc de faire appel aux classes Thread ou SynchronizationContext dans la plupart des cas. Le Dispatcher, comme son nom l’indique encapsule la logique de thread de rendu (UI) et de pompe de message Windows. On s’en sert principalement pour resynchroniser un code venant d’un autre thread.

Tous les objets WPF liés au graphique dérivent de DispatcherObject. Cette classe référence le Dispatcher de rendu et expose les méthodes CheckAccess et VerifyAccess pour vérifier que vous êtes bien dans le bon thread de rendu. Tous les contrôles graphiques appellent cette méthode avant de modifier quoi que ce soit. Le nombre d’appels à cette méthode est phénoménal mais c’est le seul moyen d’avoir une exception propre et interceptable contrairement aux appels GDI qui plantent l’application “nativement”, même en Windows Forms.

La résolution de notre problème est donc relativement simple grâce au Dispatcher qui expose des méthodes de synchronisation. Il existe même une récente méthode (.Net 4.5 ?) supportant l’await. (InvokeAsync)

private void Button_Click(object sender, RoutedEventArgs e)
{
    Task.Run(() =>
    {
        Dispatcher.BeginInvoke((Action)(() => Title = "ok"));
    });

    Task.Run(() =>
    {
        Dispatcher.InvokeAsync(() => Title = "ok");
    });
}


Jusque là quasi tout le monde connait. Je vous propose ici une autre solution sans avoir à utiliser d’action mais en personnalisant les mécanismes de code de continuation.

Vous avez surement déjà entendu “avec await, le code de continuation reprend son cours dans le même thread que le code appelant’’. Cela est très important et très appréciable car cela contribue à “simuler” un code synchrone.

Ainsi le code suivant l’instruction “await Task.Delay(1000)” continue dans le thread courant. Cette assertion n’est pourtant pas toujours vraie… Ceci n’est assuré que si vous êtes dans le thread de rendu. Pourquoi donc ? Car le thread de rendu bénéficie de la boucle principale de messages qui sera capable à un moment ou un autre de redonner la main au code de continuation.

Si ce code est appelé dans une application Console ou dans une page ASP.Net, le code de continuation sera exécuté par une thread du pool.

Si l’on préfère continuer dans un thread du pool même en étant dans un thread UI, on peut appeler: await Task.Delay(1000).ConfigureAwait(false)

Ceci aura pour effet de ne pas capturer le contexte appelant (et donc de retour).

Revenons à notre solution plus simple pour la synchronisation au thread de rendu. Mon but est que le code de continuation soit exécuté par le thread du Dispatcher et non dans une action passée en paramètre. On condamne du coup la possibilité de revenir au thread appelant. Cette solution convient donc au cas où l’on veut terminer notre méthode dans le thread de rendu.

Premièrement et comme montré précédemment, ajoutons la méthode d’extension “SwitchTo” à la classe Dispatcher. Par contre cette fois, nous allons développer notre propre Awaiter et notre propre implémentation d’INotifyCompletion !

 

public static class DispatcherExtensions
{
    public static DispatcherSynchronizer SwitchTo(this Dispatcher dispatcher, 
        DispatcherPriority priority = DispatcherPriority.Normal)
    {
        return new DispatcherSynchronizer(dispatcher, priority);
    }
}
    
public class DispatcherSynchronizer
{
    private DispatcherSynchronizerAwaiter awaiter;

    public DispatcherSynchronizer(Dispatcher dispatcher,
        DispatcherPriority priority)
    {
        awaiter = new DispatcherSynchronizerAwaiter(dispatcher, priority);
    }
    public DispatcherSynchronizerAwaiter GetAwaiter()
    {
        return awaiter;
    }
    public struct DispatcherSynchronizerAwaiter : INotifyCompletion
    {
        private Dispatcher dispatcher;
        private DispatcherPriority priority;
        public object GetResult()
        {
            return null;
        }
        public bool IsCompleted
        {
            get { return false; }
        }
        public DispatcherSynchronizerAwaiter(Dispatcher dispatcher, 
            DispatcherPriority priority)
        {
            this.dispatcher = dispatcher;
            this.priority = priority;
        }
        void INotifyCompletion.OnCompleted(Action continuation)
        {
            if (Dispatcher.CurrentDispatcher == dispatcher)
                continuation();
            else
                dispatcher.InvokeAsync(continuation, priority);
        }
    }
}

 

Le code intéressant se trouve dans la classe DispatcherSynchronizerAwaiter.

Dans notre cas, pas de valeur de retour, l’awaiter est non complété sinon OnCompleted n’est pas appelé. Je conserve à la construction de l’objet une référence sur le fameux Dispatcher.

Nous voilà enfin dans le OnCompleted ! (bravo si vous avez tenu jusque là, oui c’est un peu long)

Le paramètre “continuation” est l’Action de continuation, il nous suffit donc de l’appeler dans le contexte voulu. Si je suis déjà dans le bon Dispatcher, j’exécute l’action de manière synchrone tout simplement, sinon je synchronise grâce à InvokeAsync qui attend…une action !

Le code devient donc:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Task.Run(async () =>
    {
        await Dispatcher.SwitchTo();
        Title = "ok";
    });
}

Pas de paramètre à passer, pas de lambda. Le code de continuation s’exécute dans le thread de rendu !!

Si vous voulez revoir tout cela en image, je parle de ces mécanismes dans la session des Techdays 2014 référencée plus haut dans cet article.

Bonne lecture à tous

Catégories :CSharp Balises : , ,

Using using…

02/08/2015 5 commentaires

Moi d’aout, vacances, coding, sport, mais aussi Windows 10, VS 2015 et aussi un peu de temps pour creuser quelques idées testées dans l’année.

IMG_4479

Ici une idée très simple pour sécuriser un code encore plus simple mais qui nous embête régulièrement.

Il y a quelque années (oups 8 ans…) j’avais profité des méthodes anonymes de C# pour tester un moyen de factoriser du code “englobant” tel qu’avec les instructions try…catch.

Vous pouvez encore trouver ici mon billet relatif de l’époque.

On peut appliquer cette solution à tout type de code ayant une logique d’ouverture puis de fermeture: try…catch, début et fin de transaction, début et fin de mesure de performance, etc…

En plus de simplifier le code, ce système le sécurise également car il est vital que le code de fermeture soit appelé (Commit/Rollback, stopWatch.Stop, etc).

Par contre, on peut regretter la syntaxe toujours un peu spéciale des méthodes anonymes ou des expressions lambdas qui apportent un peu de complexité. Pour rappel, un objet est spécialement créé pour porter le contexte d’exécution d’une méthode anonyme, bref on aurait préféré l’utilisation d’un bloc de code classique et c’est tout le propos de ce billet !

Commençons par faire quelques rappels sur le mot clé “using”.

“Using” est très apprécié des développeurs C#, justement pour sa simplicité d’utilisation. Ce mot clé est intimement rattaché à l’interface IDisposable. C’est un des très rares cas où le langage est lié à un élément spécifique du framework.

 

class Program
{
    static void Main(string[] args)
    {
        using (var t = new Test())
        {
            Console.ReadLine();
        }
        Console.ReadLine();
    }
}
class Test : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("Dispose!");
    }
}

 

Dans l’exemple ci-dessus, l’instruction “using” assure l’appel de la méthode Dispose après l’exécution de l’instruction (ou du bloc d’instruction) suivant.

Si l’on désassemble l’IL compilé, on voit que le compilateur génère un bloc try…finally pour sécuriser l’appel du Dispose

 

image

On notera également que IDisposable, même si son nom pourrait le faire croire, n’est lié à aucun mécanisme de libération de mémoire. On l’utilise en général pour assurer une libération de ressource logique. Nous avons donc tout le loisir de l’utiliser pour tout autre besoin.

On peut donc facilement développer quelques classes utilisant IDisposable afin de simplifier et sécuriser l’utilisation d’un simple verrou boolean (true au démarrage, puis false en sorte) ou encore d’une mesure de temps d’exécution comme le montre les exemples ci-dessous:

 

public class SafeBooleanLock : IDisposable
{
    public bool Lock { get; private set; }
    public SafeBooleanLock()
    {
        Lock = true;
    }
    public void Dispose()
    {
        Lock = false;
    }
}
public class LogExecutionTime : IDisposable
{
    private Stopwatch sw;
    public LogExecutionTime()
    {
        sw = Stopwatch.StartNew();
    }
    public void Dispose()
    {
        sw.Stop();
        Debug.WriteLine(sw.ElapsedMilliseconds);
    }
}

 

Tout le gain est bien évidemment mesuré côté appelant, le code est factorisé, sécurisé et ce avec un simple bloc de code (sans lambda).

using (new LogExecutionTime())
{
    //Some code...
    Console.ReadLine();
}

 

Très bonnes vacances et très bonne lecture à tous !

Mitsu

Catégories :CSharp Balises : ,

iSketchnote KickStarter

Dans le cadre des technologies innovantes, nous avons eu l’opportunité chez Sensorit de collaborer avec une équipe très enthousiaste du CEA de Grenoble qui développe une technologie très prometteuse.

Ils ont mis au point un système qui permet d’équiper un stylo tout à fait banal afin d’en capturer les tracés numériquement. Nous avons eu la chance de tester cette technologie qui est très précise, extrèmement rapide et surtout passive (pas d’équipement électronique dans le stylo). Nous parlons donc de technologie grand public, très simple et bas coût.

Si les domaines d’exploitation sont vastes, la première application qui a été retenue pour le lancement de leur kickStarter est un digitaliseur pour tablette.

Le système est ultra simple, vous écrivez/dessinez sur un vrai bloc note clippé sur l’étui de la tablette. Une application dédiée capture vos tracés en temps réel. Idéal pour sketcher tout en ayant le vrai ressenti de l’écriture !

Si vous voulez participer voici le lien du kickStarter: http://kck.st/16gJmjv

Catégories :Uncategorized

Techdays 2013, coding4fun : au delà du z-order…

15/02/2013 1 commentaire

Bonjour à tous,

Comme chaque année, ce fut un grand plaisir de participer à la session coding4fun avec mes anciens collègues de Microsoft. Cette fois-ci je vous ai proposé une solution pour résoudre une problématique de z-order complexe. Quelle que soit la technologie d’affichage, traditionnellement le z-order (ou z-index) est résolu par l’ordre de dessin. Il arrive parfois que l’on veuille afficher différents éléments avec une logique plus complexe.

image

ex: un diaphragme d’appareil photo.

J’ai donc mis en place un manager qui permet de définir des associations de superposition multiples entre contrôles, y compris si ces associations finissent par être circulaires. ( A > B > C > A).

 

image

Pour ce faire, j’ai mis en place un système de recalcul dynamique du clipping des éléments afin de respecter mes règles de superposition. Chaque élément est clipé par l’ensemble de ceux qui le superposent. Afin de calculer la géométrie de clipping, je commence par translater l’ensemble des géométries des éléments dans un repère commun afin de calculer leurs intersections potentielles. La géométrie résultante est retranslaté dans le repère du controle et lui est appliquée en tant que zone de clip.

 

public class ZOrderManager
{
    public ZOrderManager()
    {
        shapes = new Dictionary<Shape, List<Shape>>();
    }

    private Dictionary<Shape, List<Shape>> shapes;

    public void IsOver(Shape foreground, Shape background)
    {
        List<Shape> children = null;
        if (shapes.TryGetValue(background, out children))
            children.Add(foreground);
        else
        {
            children = new List<Shape>();
            children.Add(foreground);
            shapes.Add(background, children);
        }
    }

    public void UpdateClipping(UIElement relativeTo)
    {
        foreach (var element in shapes)
        {
            var geom = GetRelativeGeometry(element.Key, relativeTo);
            var clip =
                element.Value.Select(s => GetRelativeGeometry(s, relativeTo))
                    .Aggregate(geom, (acc, g) =>
                        Geometry.Combine(acc, g, 
                            GeometryCombineMode.Exclude, null));
            var trans = element.Key.TransformToAncestor(relativeTo).Inverse;
            element.Key.Clip =
                Geometry.Combine(clip, Geometry.Empty, 
                    GeometryCombineMode.Union, (Transform) trans);
        }
    }

    private Geometry GetRelativeGeometry(Shape shape, UIElement relativeTo)
    {
        var trans = shape.TransformToAncestor(relativeTo);
        return Geometry.Combine(shape.RenderedGeometry, Geometry.Empty,
            GeometryCombineMode.Union, (Transform) trans);
    }
}

On peut voir ici que chaque controle est clipé permettant d’obtenir un résultat impossible à avoir juste en jouant avec l’ordre de dessin.

image
J’ai également implémenté le pseudo diaphragme en utilisant la même solution.

image
Vous trouverez ici les sources de la solution: http://sdrv.ms/11KQSCX

Qques liens vers les autres démos de la session coding4fun:

Démos de David Catuhe

Démos de David Rousset

Mitsu

Catégories :Uncategorized

Lissage: OneEuroFilter, implémentation en C# et F#

Dès lors que vous développez avec des capteurs, il se peut que le signal renvoyé ne soit pas stable ou bruité et que vous ayez à le lisser afin d’en faciliter l’exploitation. Kinect par exemple est basé sur des caméras et c’est une source qui vibre par nature. A contrario, une souris renvoie un signal stable (aucune perturbation si vous n’y touchez pas par exemple).

Si comme pour moi, le traitement du signal est plutôt un souvenir d’école, voici quelques rappels.

Tout bon informaticien ayant à lisser une série de données utilise le plus souvent le calcul d’une moyenne mobile. Pour faire simple, vous allez remplacer chaque valeur de la série par la moyenne des valeurs qui l’entourent. Ce système fonctionne mais a plusieurs défauts:

– le filtrage exploite la liste des “n” dernières valeurs sur lesquelles il faut itérer et que vous devez maintenir.

– ce système génère de la latence. La courbe sera certes lissée mais les données proches du signal d’origine arriveront plus tard dans le temps.

– la moyenne de la série est conservée mais l’écart type est diminué.

http://fr.wikipedia.org/wiki/Moyenne_mobile

D’autres filtres plus complexes offrent un paramétrage plus riche qui vous permet de mieux adapter leur comportement suivant la nature de vos données.

Parmi eux, les filtres exponentiels sont simples et couramment utilisés.

http://en.wikipedia.org/wiki/Exponential_smoothing

Dans un filtre à moyenne mobile, les valeurs les plus éloignées de l’historique “valent” autant que la dernière valeur enregistrée. Les filtres à exponentiel font décroitre de manière exponentielle le poids des valeurs selon leur éloignement dans le temps. Ces filtres lissent les données mais offrent également un comportement prédictif.

Il existe beaucoup de systèmes de filtrage plus ou moins complexes à mettre en oeuvre et offrant plus ou moins de paramètres d’entrée.

Une équipe de chercheurs de l’INRIA de Lille avec qui nous avons l’occasion d’échanger dans le domaine des intéractions vient de publier un nouveau type de filtre que nous avons utilisé au sein des projets de Sensorit, notamment avec Kinect.

L’avantage de ce filtre est principalement sa simplicité d’utilisation avec deux paramètres d’entrée permettant de lisser puis de contrer la latence.

Tous les détails ici: CHI 2012 paper (PDF)

ainsi qu’une vidéo:

 

et une page exposant l’algorithme et des implémentations dans différents langages: http://www.lifl.fr/~casiez/1euro/

Ci-dessous, une démonstration illustrant l’usage de ce filtre sur une série de données fictive.

Vous trouverez une version de l’algorithme en C# et en F# ainsi qu’un fichier zip avec l’ensemble de la solution.

 

image

 

 

C#
public class OneEuroFilter
{
    public OneEuroFilter(double minCutoff, double beta)
    {
        firstTime = true;
        this.minCutoff = minCutoff;
        this.beta = beta;

        xFilt = new LowpassFilter();
        dxFilt = new LowpassFilter();
        dcutoff = 1;
    }

    protected bool firstTime;
    protected double minCutoff;
    protected double beta;
    protected LowpassFilter xFilt;
    protected LowpassFilter dxFilt;
    protected double dcutoff;

    public double MinCutoff
    {
        get { return minCutoff; }
        set { minCutoff = value; }
    }

    public double Beta
    {
        get { return beta; }
        set { beta = value; }
    }

    public double Filter(double x, double rate)
    {
        double dx = firstTime ? 0 : (x – xFilt.Last()) * rate;
        if (firstTime)
        {
            firstTime = false;
        }

        var edx = dxFilt.Filter(dx, Alpha(rate, dcutoff));
        var cutoff = minCutoff + beta * Math.Abs(edx);

        return xFilt.Filter(x, Alpha(rate, cutoff));
    }

    protected double Alpha(double rate, double cutoff)
    {
        var tau = 1.0 / (2 * Math.PI * cutoff);
        var te = 1.0 / rate;
        return 1.0 / (1.0 + tau / te);
    }
}

public class LowpassFilter
{
    public LowpassFilter()
    {
        firstTime = true;
    }

    protected bool firstTime;
    protected double hatXPrev;

    public double Last()
    {
        return hatXPrev;
    }

    public double Filter(double x, double alpha)
    {
        double hatX = 0;
        if (firstTime)
        {
            firstTime = false;
            hatX = x;
        }
        else
            hatX = alpha * x + (1 – alpha) * hatXPrev;

        hatXPrev = hatX;

        return hatX;
    }
}

 

F#
type LowpassFilter() =
    let mutable firstTime = true
    let mutable hatXPrev = 0.0
    member v.Last() = hatXPrev
    member v.Filter(x:float, alpha:float) =
        let mutable hatX = 0
        let hatX =
            if firstTime then
                firstTime <- false
                x
            else
                alpha * x + (1.0 – alpha) * hatXPrev
        hatXPrev <- hatX
        hatX

type OneEuroFilter(minCutoff:float, beta:float) =
    let mutable firstTime = true
    let xFilt = new LowpassFilter()
    let dxFilt = new LowpassFilter()
    let mutable dcutoff = 1.0

    let mutable _minCutoff = minCutoff
    let mutable _beta = beta

    member v.MinCutoff
        with get () = _minCutoff
        and set (value) = _minCutoff <- value

    member v.Beta
        with get () = _beta
        and set (value) = _beta <- value

    member v.Filter(x:float, rate:float) =
        let Alpha rate cutoff =
            let tau = 1.0 / (2.0 * Math.PI * cutoff)
            let te = 1.0 / rate
            1.0 / (1.0 + tau / te)
        let dx = if firstTime then 0.0 else (x – xFilt.Last()) * rate
        if firstTime then firstTime <- false
        let edx = dxFilt.Filter(dx, Alpha rate dcutoff)
        let cutoff = minCutoff + beta * Math.Abs(edx)
        xFilt.Filter(x, Alpha rate cutoff)

https://skydrive.live.com/embed?cid=7BD91AE7F5096B79&resid=7BD91AE7F5096B79%21207&authkey=AKqZ6OuAtDXOFE8

Catégories :Kinect, Uncategorized

Webcasts de mes sessions Techdays 2012

Les webcasts sont disponibles !

Pour rappel j’avais précédemment fourni les sources des démos ici.

Vous trouverez ici ma session sur C# avancé, ainsi que la session Kinect Effect.

 

Bon visionnage à tous !

Catégories :Uncategorized Balises : ,

Techdays 2012 : démos C# avancé et coding4fun

08/02/2012 8 commentaires

Bonjour à tous,

Ce fut un très grand plaisir de participer encore un fois aux Techdays. Il a eu bien sûr Coding4Fun mais aussi C# avancé qui fut un grand moment. Je n’ai pas posté beaucoup depuis que j’ai ouvert ce blog à part quelques articles sur Kinect ici et , c’était donc  très sympa de repartager à nouveau avec vous.

A noter que des solutions comme le canvas infini et le framework de navigation basé sur async proviennent de réels projets développés dans le cadre de Sensorit. (je dis ça pour les taquins qui disent que je ne code que des démos !)

 

  • C# avancé : dont le principal sujet a été l’écriture d’un petite framework de navigation basé sur Async et permettant de centraliser tous les efforts de navigation à un seul endroit ou comment faire tenir toute une application dans le Loaded Smile

image

 

  • Coding4Fun

Le Canvas infini dont voici un screenshot hyper parlant !!

image

 

Et Arkanoid dans l’éditeur de code Wpf de Visual Studio, l’année prochaine ça va être vraiment très dur d’en faire un nouveau !

image

 

Pour ceux qui ont raté ou veulent revoir Coding4Fun la session est déjà en ligne car elle était diffusé en live: http://tdtv.microsoft.fr/j1/Live.aspx#fbid=t6BuyaYrGlX (dernier repère de la timeline)

Voici intégralité des sources dans un dossier skydrive.

Mitsu

Catégories :Uncategorized Balises : ,
Suivre

Recevez les nouvelles publications par mail.