Mes TechDays 2010

Cela fait maintenant presque trois ans que je n’ai pas touché à mon blog… il serait peut-être temps de s’y remettre !

Aussi vais-je parler ici des 3 jours que j’ai passés à Paris du 8 au 10 février à l’occasion des TechDays 2010. Je ne détaillerai pas l’ensemble des sessions auxquelles j’ai assisté mais me concentrerai sur les sujets qui m’ont le plus intéressé.

F#

J’ai assisté à 2 sessions sur F# ; la première était un atelier nous permettant de prendre en main le langage. La seconde était destinée à montrer de réelles applications de F#. Ces deux sessions étaient présentées par Don Syme, l’inventeur de F#, rien de moins (qui nous a aussi donné les génériques de C# 2…)

Getting Started

Pour la première session, nous avons eu droit à un tutorial sur F# qui partait réellement des bases :

printfn "Hello, World!"

Rapidement cependant, les nouveautés dans la manière de coder et de penser apparaissent. En vrac :

  • Initialisation de listes avec n’importe quelle expression énumérable,
  • Pattern-matching : sorte de super switch/case
  • Pipe : chaînage d’appels de fonctions avec l’opérateur |> : les “fluent interfaces” sont ainsi intégrées au langage.
  • Parallélisation : Async.Start, agents (MailboxProcessor) permettant la programmation parallèle par passage de messages à des agents concurrents.

Bref, si vous avez aimé les extensions ajoutées à C# 3 (types anonymes, inférence, Linq, lambdas et extensions parallèles (à venir dans .NET 4) vous adorerez F#.

Real life usage

La seconde session s’est attachée à montrer que F# était plus qu’une curiosité de laboratoire et pouvait servir dans la vraie vie au travers de trois exemples :

Tout d’abord, et l’on pourra objecter que ceci intéresse surtout les scientifiques, dans le domaine de la simulation numérique :image

Au delà de l’aspect graphique (le rendu est effectué par DirectX), cette démonstration montre les capacités en matière de parallélisation de F# : sur la capture ci-dessous, chaque anneau (les petits doughnuts blancs avec une flèche) est géré par un “agent” différent. Ce que la capture statique ci-dessus ne montre pas est que la surface est définie par une fonction de 3 paramètres dont le temps : elle est animée. Chaque anneau se déplace en suivant les contours de la surface !

Les deux autres exemples montraient d’une façon très différente comment cibler des architectures différentes lors de la compilation :

Premier exemple

Robert Pickering nous présente le jeu de la vie. Là encore, ce n’est pas tous les jours que nos clients nous demandent d’implémenter le jeu de la vie dans leur solution… Tout l’intérêt de la démonstration était ailleurs : nous avons vu tourner l’application une première fois compilée pour x64, classique et lent, puis pour la GPU ! Les cartes graphiques modernes disposent de processeurs particuliers que l’on peut qualifier d’aptes au traitement massivement parallèle : on atteint une dimension dans le parallélisme qui n’a plus grand chose à voir avec les applications classiques que l’on optimise pour 2, 4 ou 8 cœurs. Le revers de la médaille : le code a l’air tout bonnement incompréhensible (pour le peu que j’en ai vu). Cibler ce type d’architectures implique de repenser totalement les algorithmes : les objets que les GPU aiment traiter ne sont pas de bêtes variables mais des vecteurs et des matrices (et plus leurs dimensions sont élevées, plus la puissance du processeur s’exprime).

J’avoue qu’à part dans des cas spécifiques : traitement de données facilement représentable de manière matricielle, informatique scientifique, traitement d’image, je ne vois pas vraiment comment appliquer ces techniques demain dans mes projets.

Deuxième exemple

Là, on commence à toucher au monde professionnel. Adam Granicz est le fondateur de Intellifactory et il propose un outil mignon tout plein : WebSharper. En gros il s’agit d’un GWT (ou d’un Volta) à la sauce F# : du F# que du F#. Des attributs permettent de cibler le serveur ou le client et, en fonction, du code .NET classique ou du Javascript est généré.  Le layout HTML se déclare en imbriquant des listes F# : le code résultant est plutôt agréable et pas si différent de ce que de nombreux moteurs de templating MVC font. Il m’a semblé particulièrement intelligent de partir de F# pour générer du Javascript : en effet, les deux langages ont déjà beaucoup en commun (Javascript est déjà très fortement fonctionnel) et cela a du simplifier la traduction. Evidemment, les capacités parallèles de F# sont intraduisibles en Javascript (pas de multi-threading en Javascript).

Enfin, j’ai demandé à Adam Granicz quelle tête pouvaient bien avoir les pages générées : la page est-elle entièrement construite par du code Javascript dans le onLoad ou bien les balises HTML sont-elles émises ? Et bien oui et non : le rendu final en HTML est produit ce qui permet, entre autres, aux moteurs de recherche d’indexer correctement la page ; mais dès le chargement, le Javascript du onLoad supprime le DOM entier et le recrée… J’aurais peut-être préféré que le DOM reste à sa place et que le code Javascript remplisse les trous plutôt qu’il efface tout… Je suppose que de très bonnes raisons les ont poussé à faire ceci.

A noter que WebSharper intègre de nombreuses bibliothèques Javascript connues (jQuery, Yahoo UI) et les expose à F#. Le développeur peut aussi intégrer lui-même des bibliothèques Javascript (c’est une sorte d’Interop Javascript <—> F#…).

Quelques liens

System.Identity

Kim Cameron, Distinguished Engineer de la division sécurité et identité de Microsoft nous propose une session à l’intitulé alléchant ‘M’-Based System.Identity Model for Accessing Directory Services.

Il part du constat qu’Active Directory n’est pas adapté aux nouveaux besoins en matière d’identité : avec sa structure trop hiérarchique, il est difficile d’y représenter des liens entre personnes (comme le font les réseaux sociaux par exemple). Un autre point important est qu’Active Directory n’est pas abandonné, ni modifié : le nouveau modèle se place au dessus d’un AD existant : il l’étend.

Ce qui m’a le plus intéressé dans cette présentation n’est pas tant les liens avec Active Directory (d’ailleurs pas encore implémentés à l’heure actuelle) que le méta modèle sur lequel s’appuie la nouvelle architecture. Ce modèle est défini en utilisant les outils du projet Oslo (renommé récemment en SQL Server Modeling). Le langage M fait partie de ce projet est sert à décrire des modèles de niveau conceptuel. On a donc bien ici, non seulement un méta-modèle de représentation des identités numériques, mais un modèle logique. Bien que le schéma ci-dessous fasse penser à du pseudo UML, la technologie d’implémentation n’est pas définie :

612f60bc-ca21-4600-8ec8-90932ec4ff62

Dans la pratique, et dans sa version actuelle, le modèle est effectivement implémenté au dessus de SQL Server. Cependant, comme le montre ce deuxième schéma, plusieurs “providers” sont prévus, dont évidemment Active Directoy. La partie de gauche du schéma montre l’état actuel classique d’interrogation d’un annuaire Active Directory. La partie de droite, quant à elle représente le futur. L’API System.Identity permet une unification des accès aux sources de données quel que soit le type de magasin sous-jacent :

d34262e9-4193-4923-8a2e-e4276a5625f7

Dans sa présentation, Kim Cameron a donné quelques exemples d’utilisation de l’API. Le code est clair est simple, le support Intellisense complet. Cette dernière remarque semble banale et pourtant : une des forces du modèle est qu’il est extensible (soit par simple paramétrage XML pour les “Kinds” par exemple, soit en modifiant directement le modèle logique avec les outils Oslo). Un modèle modifié ou étendu est ensuite passé dans une moulinette qui génère un assembly wrapper. On dispose ainsi d’aides au codage, même sur ses propres extensions.

En bref, une présentation très intéressante. Je n’ai été déçu que sur un seul point. Bien que le titre de la présentation cite M, nous n’avons pas vu une seule ligne de code et les outils d’Oslo (Quadrant, ipad…) n’ont même pas été cités.

Quelques liens

Le blog de Kim Cameron : http://www.identityblog.com/

Autres sessions, en vrac

  • Le futur de XAML dans le framework .NET et Silverlight présenté par Mitsu Furuta de Microsoft France : System.Xaml est un nouvel assembly factorisant la sérialisation/désérialisation XAML pour toutes les technologies qui l’utilisent (WPF, Silverlight, WF…). Mitsu Furuta nous montre comment tirer partie de ces nouvelles classes pour sérialiser nos propres graphes d’objet.

  • Deux sessions présentées par SOGETI : Visual Studio : comment l’adapter à vos besoins et Comment optimiser la qualité de son code par la mise en place de bonnes pratiques :

  • La première session présente le nouveau modèle d’extensibilité de Visual Studio 2010 : déploiement simplifié et plus rapide (fichiers vsix) et plugins basés sur MEF.

  • La seconde, après avoir rappelé quelques bonnes pratiques généralement acceptées, présente le framework Code Contracts qui propose des outils d’analyse à la compilation et au runtime garantissant un code robuste (pré et post conditions, invariants). A noter que Jonathan “Peli” de Halleux était dans la salle.

  • Les nouveautés de Workflow Foundations 4

  • Fuites mémoires en .NET : Détecter et corriger.

  • Développement embarqué : Windows Embedded 6

  • Liens

     

    The "using" pattern

    In the previous post, I’ve discussed how I misused the IDisposable.Dispose() method. Here, I will present some of the ways I use the using keyword in manners that may don’t come to mind at first (I may in a few years come back to this and realize I was totally wrong, but for now, it seems to me the samples provided here may prove usefull).

    According to msdn, the using statement “Defines a scope, outside of which an object or objects will be disposed“. In the remarks section of the documentation, it is also stated that “The using statement allows the programmer to specify when objects that use resources should release them“. And the next sentence: “The object provided to the using statement must implement the IDisposable interface. This interface provides the Dispose method, which should release the object’s resources“. Everything’s ok about all this, expect one little thing: by insisting on resources, it drives people to use the using keyword only with objects holding resources, or locks, or connections or whatever needs to be released to the system…

    I think this statement can be used in an extensible manner for any object that:

    • lives in a finite scope
    • needs an action to be done when created and another one when you don’t need it any more.

    For instance, when it’s dark, and I want to write something, I need some light. So I turn it on, write my post, and turn it off before going to bed. This could be writtent this way in C#:

    SwitchOnLight();
    WriteThisPost();
    SubmitIt();   
    SwitchOffLight();
    GotoBed();

    There are times when I’m quite tired, and I may forget to switch off the light before going to bed. This results in this code:

    SwitchOnLight();
    WriteThisPost();
    SubmitIt();   
    GotoBed();

    Here, C# programmers will have recognized that some kind of Dispose() call is missing. Enters the using keyword which allows me to write:

    using(Light)

        WriteThisPost();
        SubmitIt();    
    }
    GoToBed();

    And thus, I never forget to turn off the light before going to bed.

    I really like the metaphor the using keyword provides, and I’d like to be able to use it even for objects that don’t hold any system resource. As the samples below demonstrate it, there’s nothing preventing me from doing so. The main idea is that any object that needs to do something when created, and something else when released is a good candidate for the using keyword: these two tasks are implemented in the constructor and in the IDisposable.Dispose() method. The task executed in the Dispose() method hasn’t to release resources. In fact, most of the times, It just restores a saved state.

    Example 1:

    In most of my windows forms applications, I use a base form class providing some goodies to inheritors (one of them is a wonderfull linear gradient I apply on the background of my forms – question of taste). Among these services is WaitCursor. Usually when you want to show an hourglass cursor while processing a lengthy task, you have to follow three steps:

    1. Change the cusor: this.Cursor = Cursors.WaitCursor;
    2. Execute the lengthy task in a try block
    3. Restore the normal cursor in a finally clause: finally { this.Cursor = Cursors.Default; }

    I’ve built up a little helper class (completed with a property) which allows you to write this code, (which seems more readable to me : it’s almost well formed English):

    using(WaitCursor) { /* execute lengthy task */ }

    First, in the base form class, WaitCursor is a property returning an IDisposable:

    protected IDisposable WaitCursor
    {
             get { return new CursorProvider(this, Cursors.Wait); }
    }

    And CursorProvider is a private inner class also defined in the base form class:

    private class CursorProvider : IDisposable
    {
            Control owner = null;
            Cursor savedCursor = Cursors.Default;

            public CursorProvider(Control control, Cursor newCursor)
            {
                if (control == null)
                    throw new ArgumentNullException(“control”);
                if (newCursor == null) 
                    throw new ArgumentNullException(“newCursor”);

                owner = control;
                savedCursor = control.Cursor;
                control.Cursor = newCursor;
                control.Refresh();
            }

            #region IDisposable Members

            public void Dispose() { owner.Cursor = savedCursor; }

            #endregion
    }

    A few explanations:

    • The property is returning an IDisposable instance: indeed, callers don’t have to know anything else (it is intendeed to be part of a using statement) so, why would I expose more?
    • Each time the property is called, a new object is created: you can overlap as many using statements as you wish, after the last closing bracket, the correct cursor will be restored.
    • We never need the object created by the call to the property, thus the using(WaitCursor) and not some using(IDisposable foo = WaitCursor).
    • The class is straightforward: the constructor, after checking for null parameters, saves the current state (the current control’s cursor) then sets the new state. Inside Dispose() (which will always be called at the end of the using block, wether an exception has been thrown or not), the state is restored.

    Example 2: Saving the state of a Graphics object. In this old post, I exposed a way of using the GraphicsContainer class. And I wrapped it in an IDisposable object (one time again, the idea is to save a state in the constructor, and to restore it in Dispose()).

    Example 3: .NET Matters: Scope and more. In this article from MSDN Magazine, Stephen Toub explains how to code a Scope<T> class to provide transactionnal behavior. This is an advanced example of a class that fits perfectly well with the using syntax. Besides the link with this post regarding the using statement, this article also discusses many other interesting .NET concepts (and in particular, the notion of thread static members). The second short article about the Semaphore class is again an example of a pretty use of the using statement.

    Mea culpa: the IsDisposed anti-pattern

    Back a few years ago, when I was still a new-born at C# and .NET programming, I had found myself very proud for having improved the .NET framework itself. Indeed, I had just invented the IDisposableEx interface:

    public interface IDisposableEx : IDisposable
    {
         bool IsDisposed { get; }
    }

    What did I use this interface for? It seemed to me a great improvement to be able to know whether or not an object had been disposed. And I was writing code like this:

    if (!myObject.IsDisposed) myObject.Dispose();

    Here lie two style errors:

    1. Not so a serious one: why calling Dispose() when a using construct would make it perfectly useless (As of now, I only call Dispose() when the object is not instanciated in the method that will dispose it)?
    2. The real big one: what is the use of the test on the disposed state of the object? Microsoft clearly states that a Dispose() method call should NEVER EVER fail (see msdn). One could call Dispose() thousands of times, there should never happen any exception. So, the test is useless.

    On the other hand, one could argue that testing the disposed state of the object isn’t that serious… and I agree with this; in fact, what is really misconcepted in the IDisposableEx interface is not how you use it, but what it supposes can happen inside the implementor: by allowing to test the disposed state, this interface suggests that the behavior of the Dispose() method depends on the state of the object. And even worse: if you call Dispose() and the IsDisposed property was true, then Dispose() might fail! And in some of my implementations, it did! In my mind providing a means of testing was good enough, and if your app ended with an uncaught exception, it was the developper’s fault: why didn’t you test IsDisposed?… my apologies go to them… 

    The correct way to handle multiple calls to Dispose() is actually to store a disposed state, but it must be inner to the object and calling code must never rely on it (so I’d  better make this private, and remove the IDisposableEx interface – from source control if I can, so that no one ever discovers my crime):

    private bool disposed = false;

    public void Dispose()
    {
        if (disposed) return;

        // disposing of allocated resources
        …
        // now, don’t forget to set the disposed state

        disposed = true;
    }

    I hope that having revealed a part of my dark past will help you not to make that mistake, or at least will it have made you laugh a bit.

     

    PS: I can’t think of a scenario right now where a caller should be aware of the disposed state of the callee, but in such a case, the IsDisposed property seems acceptable (if you don’t want to catch numbers of ObjectDisposedException). But I think this would be a really bad idea to provide this property as part of an interface… Or at least should this interface be named something like IDisposedStateNotifier so that developpers don’t think it modifies the IDisposable.Dispose standard behavior…

    Log4Net: IP parsing bug when used with framework .NET 2.0

    Update (2008/08/21):

    As stated by SergeS in his comment, the solution I provide below (while working)  should not be used any more. Instead, replace your src/Appender/UdpAppender.cs file with the one found here:

    https://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/UdpAppender.cs?revision=506603

    I’m using log4net 1.2.10 for a few month now and couldn’t ever get rid of it. Today I was playing with the udp appender: I was trying to have my application send logs via udp to Log4NetViewer… and nothing happened. After having enabled the log4net debug mode (1), I could see there was something wrong with the way log4net parsed my IP (2):

    log4nelog4net:ERROR [UdpAppender] Unable to send logging event to remote host ::1 on port 1234.
    System.Net.Sockets.SocketException: Une adresse incompatible avec le protocole demandé a été utilisée
    à System.Net.Sockets.Socket.SendTo(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint remoteEP)
    à System.Net.Sockets.UdpClient.Send(Byte[] dgram, Int32 bytes, IPEndPoint endPoint)
    à log4net.Appender.UdpAppender.Append(LoggingEvent loggingEvent)

    log4net was transforming my “192.168.0.2” parameter IP into ::1, and the problem took place in the method IPAddressConverter.ConvertFrom() (the file is located under log4net-1.2.10\src\Util\TypeConverters\IPAddressConverter.cs).
    The problem is that when compiled with .NET 2.0, the original code is returning the first IP address associated with the host (host itself returned by a dns lookup):

    IPHostEntry host = Dns.GetHostEntry(str);
    if (host != null &&
        host.AddressList != null &&
        host.AddressList.Length > 0 &&
        host.AddressList[0] != null)
    { 
        return host.AddressList[0];
    }

    When inspecting the content of this address list with the debugger I got:

    + [0] {::1} System.Net.IPAddress
    + [1] {192.168.0.2} System.Net.IPAddress
    + [2] {192.168.206.1} System.Net.IPAddress
    + [3] {192.168.114.1} System.Net.IPAddress

    So, with the existing code, the address ::1 is selected… and the UdpAppender throws an exception 😦 To avoid this:
    first I added this property to IPAddressConverter:

    public bool IsIPv6Supported { get { return false; } }

    note that I’m not networking aware, and thus this may be replaced by some code able to detect wether or not IP v6 is supported…
    then I replaced “
    return host.AddressList[0];” with:

    foreach (IPAddress address in host.AddressList)
    {
        if ((address.AddressFamily ==
            System.Net.Sockets.AddressFamily.InterNetworkV6) &&
            !IsIPv6Supported) 
            continue;
                                    
        return address;
    }
    This way, I return the first IPv4 address instead of the first address.Hope this helps 

    (1) to do so, just add the following xml to your app.config:

    <appSettings>
    <add key=log4net.Internal.Debug value=true/>
    </
    appSettings>

    (2) aproximatively translated from French into English: The used address is incompatible with the requested protocol

    PS: if you want to compile the log4net visual studio project provided with the distribution, you have to apply these guidelines: http://logging.apache.org/log4net/release/building.html#vsnet-2005

    .NET 3.0 is out!

    Great news: .NET Framework 3.0 has been released!

    Formerly known as WinFx, the .NET framework 3.0 is a set of (3 main) components built on top of the .NET framework 2.0 (this means that this “3rd” version is 100% compatible with .NET 2.0: it is pure .NET 2.0 code…):

    • Windows communication foundation (formerly known as Indigo)
    • Windows workflow foundation
    • Windows presentation foundation (formerly known as Avalon)
    • and the little last one: Cardspace

    Useful memo: Windows messages

    Grabbed from this url (may only contain most useful definitions): http://www.groupsrv.com/dotnet/about52848.html:

    WM_NULL = 0x0000,
    WM_CREATE = 0x0001,
    WM_DESTROY = 0x0002,
    WM_MOVE = 0x0003,
    WM_SIZE = 0x0005,
    WM_ACTIVATE = 0x0006,
    WM_SETFOCUS = 0x0007,
    WM_KILLFOCUS = 0x0008,
    WM_ENABLE = 0x000A,
    WM_SETREDRAW = 0x000B,
    WM_SETTEXT = 0x000C,
    WM_GETTEXT = 0x000D,
    WM_GETTEXTLENGTH = 0x000E,
    WM_PAINT = 0x000F,
    WM_CLOSE = 0x0010,
    WM_QUERYENDSESSION = 0x0011,
    WM_QUIT = 0x0012,
    WM_QUERYOPEN = 0x0013,
    WM_ERASEBKGND = 0x0014,
    WM_SYSCOLORCHANGE = 0x0015,
    WM_ENDSESSION = 0x0016,
    WM_SHOWWINDOW = 0x0018,
    WM_CTLCOLOR = 0x0019,
    WM_WININICHANGE = 0x001A,
    WM_SETTINGCHANGE = 0x001A,
    WM_DEVMODECHANGE = 0x001B,
    WM_ACTIVATEAPP = 0x001C,
    WM_FONTCHANGE = 0x001D,
    WM_TIMECHANGE = 0x001E,
    WM_CANCELMODE = 0x001F,
    WM_SETCURSOR = 0x0020,
    WM_MOUSEACTIVATE = 0x0021,
    WM_CHILDACTIVATE = 0x0022,
    WM_QUEUESYNC = 0x0023,
    WM_GETMINMAXINFO = 0x0024,
    WM_PAINTICON = 0x0026,
    WM_ICONERASEBKGND = 0x0027,
    WM_NEXTDLGCTL = 0x0028,
    WM_SPOOLERSTATUS = 0x002A,
    WM_DRAWITEM = 0x002B,
    WM_MEASUREITEM = 0x002C,
    WM_DELETEITEM = 0x002D,
    WM_VKEYTOITEM = 0x002E,
    WM_CHARTOITEM = 0x002F,
    WM_SETFONT = 0x0030,
    WM_GETFONT = 0x0031,
    WM_SETHOTKEY = 0x0032,
    WM_GETHOTKEY = 0x0033,
    WM_QUERYDRAGICON = 0x0037,
    WM_COMPAREITEM = 0x0039,
    WM_GETOBJECT = 0x003D,
    WM_COMPACTING = 0x0041,
    WM_COMMNOTIFY = 0x0044 ,
    WM_WINDOWPOSCHANGING = 0x0046,
    WM_WINDOWPOSCHANGED = 0x0047,
    WM_POWER = 0x0048,
    WM_COPYDATA = 0x004A,
    WM_CANCELJOURNAL = 0x004B,
    WM_NOTIFY = 0x004E,
    WM_INPUTLANGCHANGEREQUEST = 0x0050,
    WM_INPUTLANGCHANGE = 0x0051,
    WM_TCARD = 0x0052,
    WM_HELP = 0x0053,
    WM_USERCHANGED = 0x0054,
    WM_NOTIFYFORMAT = 0x0055,
    WM_CONTEXTMENU = 0x007B,
    WM_STYLECHANGING = 0x007C,
    WM_STYLECHANGED = 0x007D,
    WM_DISPLAYCHANGE = 0x007E,
    WM_GETICON = 0x007F,
    WM_SETICON = 0x0080,
    WM_NCCREATE = 0x0081,
    WM_NCDESTROY = 0x0082,
    WM_NCCALCSIZE = 0x0083,
    WM_NCHITTEST = 0x0084,
    WM_NCPAINT = 0x0085,
    WM_NCACTIVATE = 0x0086,
    WM_GETDLGCODE = 0x0087,
    WM_SYNCPAINT = 0x0088,
    WM_NCMOUSEMOVE = 0x00A0,
    WM_NCLBUTTONDOWN = 0x00A1,
    WM_NCLBUTTONUP = 0x00A2,
    WM_NCLBUTTONDBLCLK = 0x00A3,
    WM_NCRBUTTONDOWN = 0x00A4,
    WM_NCRBUTTONUP = 0x00A5,
    WM_NCRBUTTONDBLCLK = 0x00A6,
    WM_NCMBUTTONDOWN = 0x00A7,
    WM_NCMBUTTONUP = 0x00A8,
    WM_NCMBUTTONDBLCLK = 0x00A9,
    WM_KEYDOWN = 0x0100,
    WM_KEYUP = 0x0101,
    WM_CHAR = 0x0102,
    WM_DEADCHAR = 0x0103,
    WM_SYSKEYDOWN = 0x0104,
    WM_SYSKEYUP = 0x0105,
    WM_SYSCHAR = 0x0106,
    WM_SYSDEADCHAR = 0x0107,
    WM_KEYLAST = 0x0108,
    WM_IME_STARTCOMPOSITION = 0x010D,
    WM_IME_ENDCOMPOSITION = 0x010E,
    WM_IME_COMPOSITION = 0x010F,
    WM_IME_KEYLAST = 0x010F,
    WM_INITDIALOG = 0x0110,
    WM_COMMAND = 0x0111,
    WM_SYSCOMMAND = 0x0112,
    WM_TIMER = 0x0113,
    WM_HSCROLL = 0x0114,
    WM_VSCROLL = 0x0115,
    WM_INITMENU = 0x0116,
    WM_INITMENUPOPUP = 0x0117,
    WM_MENUSELECT = 0x011F,
    WM_MENUCHAR = 0x0120,
    WM_ENTERIDLE = 0x0121,
    WM_MENURBUTTONUP = 0x0122,
    WM_MENUDRAG = 0x0123,
    WM_MENUGETOBJECT = 0x0124,
    WM_UNINITMENUPOPUP = 0x0125,
    WM_MENUCOMMAND = 0x0126,
    WM_CTLCOLORMSGBOX = 0x0132,
    WM_CTLCOLOREDIT = 0x0133,
    WM_CTLCOLORLISTBOX = 0x0134,
    WM_CTLCOLORBTN = 0x0135,
    WM_CTLCOLORDLG = 0x0136,
    WM_CTLCOLORSCROLLBAR = 0x0137,
    WM_CTLCOLORSTATIC = 0x0138,
    WM_MOUSEMOVE = 0x0200,
    WM_LBUTTONDOWN = 0x0201,
    WM_LBUTTONUP = 0x0202,
    WM_LBUTTONDBLCLK = 0x0203,
    WM_RBUTTONDOWN = 0x0204,
    WM_RBUTTONUP = 0x0205,
    WM_RBUTTONDBLCLK = 0x0206,
    WM_MBUTTONDOWN = 0x0207,
    WM_MBUTTONUP = 0x0208,
    WM_MBUTTONDBLCLK = 0x0209,
    WM_MOUSEWHEEL = 0x020A,
    WM_PARENTNOTIFY = 0x0210,
    WM_ENTERMENULOOP = 0x0211,
    WM_EXITMENULOOP = 0x0212,
    WM_NEXTMENU = 0x0213,
    WM_SIZING = 0x0214,
    WM_CAPTURECHANGED = 0x0215,
    WM_MOVING = 0x0216,
    WM_DEVICECHANGE = 0x0219,
    WM_MDICREATE = 0x0220,
    WM_MDIDESTROY = 0x0221,
    WM_MDIACTIVATE = 0x0222,
    WM_MDIRESTORE = 0x0223,
    WM_MDINEXT = 0x0224,
    WM_MDIMAXIMIZE = 0x0225,
    WM_MDITILE = 0x0226,
    WM_MDICASCADE = 0x0227,
    WM_MDIICONARRANGE = 0x0228,
    WM_MDIGETACTIVE = 0x0229,
    WM_MDISETMENU = 0x0230,
    WM_ENTERSIZEMOVE = 0x0231,
    WM_EXITSIZEMOVE = 0x0232,
    WM_DROPFILES = 0x0233,
    WM_MDIREFRESHMENU = 0x0234,
    WM_IME_SETCONTEXT = 0x0281,
    WM_IME_NOTIFY = 0x0282,
    WM_IME_CONTROL = 0x0283,
    WM_IME_COMPOSITIONFULL = 0x0284,
    WM_IME_SELECT = 0x0285,
    WM_IME_CHAR = 0x0286,
    WM_IME_REQUEST = 0x0288,
    WM_IME_KEYDOWN = 0x0290,
    WM_IME_KEYUP = 0x0291,
    WM_MOUSEHOVER = 0x02A1,
    WM_MOUSELEAVE = 0x02A3,
    WM_CUT = 0x0300,
    WM_COPY = 0x0301,
    WM_PASTE = 0x0302,
    WM_CLEAR = 0x0303,
    WM_UNDO = 0x0304,
    WM_RENDERFORMAT = 0x0305,
    WM_RENDERALLFORMATS = 0x0306,
    WM_DESTROYCLIPBOARD = 0x0307,
    WM_DRAWCLIPBOARD = 0x0308,
    WM_PAINTCLIPBOARD = 0x0309,
    WM_VSCROLLCLIPBOARD = 0x030A,
    WM_SIZECLIPBOARD = 0x030B,
    WM_ASKCBFORMATNAME = 0x030C,
    WM_CHANGECBCHAIN = 0x030D,
    WM_HSCROLLCLIPBOARD = 0x030E,
    WM_QUERYNEWPALETTE = 0x030F,
    WM_PALETTEISCHANGING = 0x0310,
    WM_PALETTECHANGED = 0x0311,
    WM_HOTKEY = 0x0312,
    WM_PRINT = 0x0317,
    WM_PRINTCLIENT = 0x0318,
    WM_HANDHELDFIRST = 0x0358,
    WM_HANDHELDLAST = 0x035F,
    WM_AFXFIRST = 0x0360,
    WM_AFXLAST = 0x037F,
    WM_PENWINFIRST = 0x0380,
    WM_PENWINLAST = 0x038F,
    WM_APP = 0x8000,
    WM_USER = 0x0400,
    WM_REFLECT = WM_USER + 0x1c00

    Impossible de lancer le debugger de Visual Studio 2005

    Le message d’erreur qui apparaît lorsque l’on lance un programme depuis Visual Studio 2005 (ou depuis une version Express) est, en français : Handle de liaison invalide ; ce message correspond, en anglais à The binding handle is invalid.

    Ce problème apparaît lorsque le service Terminal Server est désactivé. Il suffit donc de relancer ce service pour que tout rentre dans l’ordre.

    Pour plus de détails, voir les posts suivants (en anglais) :

    Troubleshooting the “The Binding Handle Is Invalid” error in Visual Studio 2005

    Explaining ‘The Binding Handle Is Invalid’

    “The Binding Handle Is Invalid” error in Visual Studio 2005

    Saving the state of a Graphics object

    Today I discovered a new class : GraphicsContainer; it allows you to save the state of a Graphics object (transformation, clipping region, and rendering properties) and to restore it later. This class is used in conjunction with 2 pairs of methods belonging to the Graphics class: BeginContainer saves the state of the graphics object (and returns a GraphicsContainer object), EndContainer restores the state (when provided with a GraphicsContainer object). MSDN provides a sample here: http://msdn2.microsoft.com/en-us/library/azdschfw.aspx. There exists overloads of BeginContainer that accept two rectangles and unit allowing the Graphics object to be applied a new transformation after its state is saved. In the same maneer, but in a simpler way, the Graphics.Save and Graphics.Restore methods do the same job (Honestly, I don’t understand why these two pairs of methods coexist…) This led me to write a little helper class allowing to save/restore a Graphics with the using syntax. Here is how to use this class (it is just a rewritten version of the MSDN):

    protected override void OnPaint( System.Windows.Forms.PaintEventArgs e) { Graphics g = e.Graphics; // Define transformation for container. RectangleF src = new RectangleF( 0f, 0f, 200f, 200f); RectangleF dest = new RectangleF( 100f, 100f, 150f, 150f); using (PaintHelper.SaveGraphics( g, dest, src, GraphicsUnit.Pixel)) { // Fill red rectangle in container. g.FillRectangle(Brushes.Red, 0.0F, 0.0F, 200.0F, 200.0F); } // Fill untransformed rectangle with green. g.FillRectangle(Brushes.Green, 0.0F, 0.0F, 200.0F, 200.0F); }

    And the source code for the PaintHelper class:

    using System;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    
    namespace Delta.Internals
    {
        public static class PaintHelper
        {
            private class GraphicsBackup : IDisposable
            {
                private Graphics graphics = null;
                private GraphicsContainer container = null;
    
                public GraphicsBackup(Graphics g)
                {
                    Init(g);
                    container = g.BeginContainer();
                }
    
                public GraphicsBackup(
                     Graphics g, Rectangle dest, Rectangle src,
                     GraphicsUnit unit)
                {
                    container = g.BeginContainer(
    dest, src, unit); } public GraphicsBackup( Graphics g, RectangleF dest, RectangleF src, GraphicsUnit unit) { container = g.BeginContainer(
    dest, src, unit); } private void Init(Graphics g) { if (g == null) throw new ArgumentNullException("g"); graphics = g; } public void Dispose() { graphics.EndContainer(container); } } public static IDisposable SaveGraphics(Graphics g) { return new GraphicsBackup(g); } public static IDisposable SaveGraphics(Graphics g, Rectangle dest, Rectangle src, GraphicsUnit unit) { return new GraphicsBackup( g, dest, src, unit); } public static IDisposable SaveGraphics(Graphics g, RectangleF dest, RectangleF src, GraphicsUnit unit) { return new GraphicsBackup( g, dest, src, unit); } } }

    Hope this helps.

    Pattern singleton thread safe en C# : c’est facile

    Lu ici : http://www.dofactory.com/Patterns/PatternSingleton.aspx

    Voici la manière classique d’écrire un pattern singleton thread-safe en C# :

    class MySingleton
    {
        private static MySingleton instance;
    
    // Lock synchronization object
        private static object syncLock = new object();
    
    private MySingleton() { DoSomething(); }
    
    public static MySingleton Instance
        {
            get
            {
                // Support multithreaded applications
                // through 'Double checked locking'
                // pattern which (once the instance
                // exists) avoids locking each
                // time the method is invoked
                if (instance == null)
                {
                    lock (syncLock)
                    {
                        if (instance == null)
                            instance = new MySingleton();
                    }
                }
                return instance;
            }
        }
    }

    Et maintenant, voici la manière “.NET” d’écrire ce même singleton :

    class MySingleton
    {
        // Static members are lazily initialized.
        // .NET guarantees thread safety for
        // static initialization
        private static readonly MySingleton instance =
                            new MySingleton();
    
    // Constructor (private)
        private MySingleton() { DoSomething(); }
    
    public static MySingleton Instance { get { return instance; } }
    }

    ça marche parce que “private static readonly” entraîne :

    • Initialisation paresseuse
    • Thread-safety garantie par .NET pour les initialisations statiques.

    C’est pas beau ça ?