<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C# - In Fine - Le Blog</title>
	<atom:link href="https://blog.infine.com/category/csharp/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.infine.com</link>
	<description>Le blog des technos de demain !</description>
	<lastBuildDate>Mon, 11 Oct 2021 13:11:47 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.5.7</generator>

<image>
	<url>https://blog.infine.com/wp-content/uploads/2021/03/cropped-vignette-32x32.png</url>
	<title>C# - In Fine - Le Blog</title>
	<link>https://blog.infine.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>From C# to SIMD : Numerics.Vector and Hybridizer</title>
		<link>https://blog.infine.com/from-c-to-simd-numerics-vector-and-hybridizer-3339?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=from-c-to-simd-numerics-vector-and-hybridizer</link>
					<comments>https://blog.infine.com/from-c-to-simd-numerics-vector-and-hybridizer-3339#respond</comments>
		
		<dc:creator><![CDATA[Florent]]></dc:creator>
		<pubDate>Wed, 06 Oct 2021 08:49:00 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Hybridizer]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=3339</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">5</span> <span class="rt-label rt-postfix">min.</span></span> System.Numerics.Vector&#160;is a library provided by .Net (as a nuget package), which tries to leverage SIMD instruction on target hardware. It exposes a few value types, such as&#160;Vector&#60;T&#62;, which are recognized by&#160;RyuJIT&#160;as intrinsics.Supported intrinsics are listed in the&#160;core-clr github repository.This allows C# SIMD acceleration, as long as code is modified to use these intrinsic types, instead &#8230;</p>
<p>The post <a href="https://blog.infine.com/from-c-to-simd-numerics-vector-and-hybridizer-3339">From C# to SIMD : Numerics.Vector and Hybridizer</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">5</span> <span class="rt-label rt-postfix">min.</span></span>
<p><a href="https://msdn.microsoft.com/en-us/library/dn858218(v=vs.111).aspx" target="_blank" rel="noopener">System.Numerics.Vector</a>&nbsp;is a library provided by .Net (as a nuget package), which tries to leverage SIMD instruction on target hardware. It exposes a few value types, such as&nbsp;<code>Vector&lt;T&gt;</code>, which are recognized by&nbsp;<a href="https://blogs.msdn.microsoft.com/dotnet/2013/09/30/ryujit-the-next-generation-jit-compiler-for-net/" target="_blank" rel="noopener">RyuJIT</a>&nbsp;as intrinsics.<br>Supported intrinsics are listed in the&nbsp;<a href="https://raw.githubusercontent.com/dotnet/coreclr/master/src/jit/simdintrinsiclist.h" target="_blank" rel="noopener">core-clr github repository</a>.<br>This allows C# SIMD acceleration, as long as code is modified to use these intrinsic types, instead of scalar floating point elements.</p>



<p>On the other hand, Hybridizer aims to provide those benefits without being intrusive in the code (only metadata is required).</p>



<p>We naturally wanted to test if System.Numerics.Vector delivers good performance, compared to Hybridizer.</p>



<figure class="wp-block-table"><table><tbody><tr><td><strong>Summary</strong><br>We measured that Numerics.Vector provides good speed-up over C# code as long as no transcendental function is involved (such as Math.Exp), but still lags behind Hybridizer. Because of the lack of some operators and mathematical functions, Numerics can also generate really slow code (when AVX pipeline is broken). In addition, code modification is a heavy process, and can’t easily be rolled back.</td></tr></tbody></table></figure>



<p>We wrote and ran two benchmarks, and for each of them we have four versions:</p>



<ul><li>Simple C# scalar code</li><li>Numerics.Vector</li><li>Simple C# scalar code, hybridized</li><li>Numerics.Vector, hybridized</li></ul>



<p>Processor is a&nbsp;<a href="http://ark.intel.com/products/75124/Intel-Core-i7-4770S-Processor-8M-Cache-up-to-3_90-GHz" target="_blank" rel="noopener">core i7-4770S @ 3.1GHz</a>&nbsp;(max measured turbo in AVX mode being 3.5GHz). Peak flops is 224 GFlop/s, or 112 GCFlop/s, if we count&nbsp;<a href="https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation" target="_blank" rel="noopener">FMA&nbsp;</a>as one (since our processor supports it).</p>



<h2 class="wp-block-heading">Compute bound benchmark</h2>



<p>This is a compute-intensive benchmark. For each element of a large double precision array (8 millions elements: 67MBytes), we iterate twelve times the computation of an exponential’s Taylor expansion (expm1). This is largely enough to enter the compute-bound world, by hiding memory operations latency behind a full bunch of floatin point operations.<br>Scalar code is simply:</p>





<pre class="wp-block-code"><code lang="csharp" class="language-csharp"> [MethodImpl(MethodImplOptions.AggressiveInlining)]
 public static double expm1(double x)
 {
   return ((((((((((((((15.0 + x)
     * x + 210.0)
     * x + 2730.0)
     * x + 32760.0)
     * x + 360360.0)
     * x + 3603600.0)
     * x + 32432400.0)
     * x + 259459200.0)
     * x + 1816214400.0)
     * x + 10897286400.0)
     * x + 54486432000.0)
     * x + 217945728000.0)
     * x + 653837184000.0)
     * x + 1307674368000.0)
     * x * 7.6471637318198164759011319857881e-13;
 }
 [MethodImpl(MethodImplOptions.AggressiveInlining)]
 public static double twelve(double x)
 {
   return expm1(expm1(expm1(expm1(expm1(expm1(expm1(expm1(expm1(expm1(expm1(x)))))))))));
 } </code></pre>



<p>on which we added the&nbsp;<a href="https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions(v=vs.110).aspx" target="_blank" rel="noopener">AggressiveInlining&nbsp;</a>attribute to help RyuJit to merge operations at JIT time.</p>



<p>The Numerics.Vector version of the code is quite the same:</p>



<pre class="wp-block-code"><code lang="csharp" class="language-csharp"> [MethodImpl(MethodImplOptions.AggressiveInlining)]
 public static Vector&lt;double> expm1(Vector&lt;double> x)
 {
   return ((((((((((((((new Vector&lt;double>(15.0) + x)
     * x + new Vector&lt;double>(210.0))
     * x + new Vector&lt;double>(2730.0))
     * x + new Vector&lt;double>(32760.0))
     * x + new Vector&lt;double>(360360.0))
     * x + new Vector&lt;double>(3603600.0))
     * x + new Vector&lt;double>(32432400.0))
     * x + new Vector&lt;double>(259459200.0))
     * x + new Vector&lt;double>(1816214400.0))
     * x + new Vector&lt;double>(10897286400.0))
     * x + new Vector&lt;double>(54486432000.0))
     * x + new Vector&lt;double>(217945728000.0))
     * x + new Vector&lt;double>(653837184000.0))
     * x + new Vector&lt;double>(1307674368000.0))
     * x * new Vector&lt;double>(7.6471637318198164759011319857881e-13);
} </code></pre>



<p>The four versions of this code give the following performance results:</p>



<figure class="wp-block-table"><table><tbody><tr><td>Flavor</td><td>Scalar C#</td><td>Vector C#</td><td>Vector Hyb</td><td>Scalar Hyb</td></tr><tr><td>GCFlop/s</td><td>4.31</td><td>19.95</td><td>41.29</td><td>59.65</td></tr></tbody></table></figure>



<div class="wp-block-image"><figure class="aligncenter"><a href="http://www.altimesh.com/wp-content/uploads/2017/06/expm1-numerics-vector-speedup.png" class="fancyboxgroup" rel="gallery-3339"><img decoding="async" src="http://hybridizer.io/wp-content/uploads/2017/06/expm1-numerics-vector-speedup.png" alt="" class="wp-image-237"/></a></figure></div>



<p>As stated, Numerics.Vector delivers a close to 4x speedup from scalar. However, performance is far from what we reach with the Hybridizer. If we look at generated assembly, it’s quite clear why:</p>



<pre class="wp-block-code"><code lang="c" class="language-c"> vbroadcastsd ymm0,mmword ptr [7FF7C2255B48h]
 vbroadcastsd ymm1,mmword ptr [7FF7C2255B50h]
 vbroadcastsd ymm2,mmword ptr [7FF7C2255B58h]
 vbroadcastsd ymm3,mmword ptr [7FF7C2255B60h]
 vbroadcastsd ymm4,mmword ptr [7FF7C2255B68h]
 vbroadcastsd ymm5,mmword ptr [7FF7C2255B70h]
 vbroadcastsd ymm7,mmword ptr [7FF7C2255B78h]
 vbroadcastsd ymm8,mmword ptr [7FF7C2255B80h]
 vaddpd ymm0,ymm0,ymm6 
 vmulpd ymm0,ymm0,ymm6
 vaddpd ymm0,ymm0,ymm1
 vmulpd ymm0,ymm0,ymm6
 vaddpd ymm0,ymm0,ymm2
 vmulpd ymm0,ymm0,ymm6
 vaddpd ymm0,ymm0,ymm3
 vmulpd ymm0,ymm0,ymm6
 vaddpd ymm0,ymm0,ymm4
 vmulpd ymm0,ymm0,ymm6
 vaddpd ymm0,ymm0,ymm5
 vmulpd ymm0,ymm0,ymm6
 vaddpd ymm0,ymm0,ymm7
 vmulpd ymm0,ymm0,ymm6
 vaddpd ymm0,ymm0,ymm8
 vmulpd ymm0,ymm0,ymm6
 ; repeated </code></pre>



<p>Fused multiply add are not reconstructed, and constant operands are reloaded from constant pool at each expm1 invokation. This leads to high registry pressure (for constants), where memory operands could save some.</p>



<p>Here is what the Hybridizer generates from scalar code:</p>



<pre class="wp-block-code"><code lang="csharp" class="language-csharp"> vaddpd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vfmadd213pd ymm1,ymm0,ymmword ptr []
 vmulpd ymm0,ymm0,ymm1&lt;br /&gt;
 vmulpd ymm0,ymm0,ymmword ptr []
 vmovapd ymmword ptr [rsp+0A20h],ymm0
 ; repeated </code></pre>



<p><br>This reconstructs fused multiply-add, and leverages memory operands to save registers.</p>



<p>Why are we not to peak performance (112GCFlops)? That is because Haswell has two pipelines for FMA, and a latency of 5 (see&nbsp;<a href="https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=FMA&amp;expand=2595,2381" target="_blank" rel="noopener">intel intrinsic guide</a>. To reach peak performance, we would need to interleave 2 independant FMA instruction at each cycle. This could be done by reordering instructions, since&nbsp;<a href="http://www.anandtech.com/show/6355/intels-haswell-architecture/8" target="_blank" rel="noopener">reorder buffer</a>&nbsp;is not long enough to execute instructions too far in the pipeline. LLVM, our backend compiler, is not capable of such reordering. To get better performance, we unfortunately have to write assembly by hand (which is not exactly what a C# programmer expects to do in the morning).</p>



<h2 class="wp-block-heading">Invoke transcendentals</h2>



<p>In this second benchmark, we need to compute the exponential of all the components of a vector. To do that, we invoke&nbsp;<a href="https://msdn.microsoft.com/en-us/library/system.math.exp(v=vs.110).aspx" target="_blank" rel="noopener">Math.Exp</a>.<br>Scalar code is:</p>





<pre class="wp-block-code"><code lang="csharp" class="language-csharp"> [EntryPoint]
 public static void Apply_scal(double[] d, double[] a, double[] b, double[] c, int start, int stop)
 {
   int sstart = start + threadIdx.x + blockDim.x * blockIdx.x;
   int step = blockDim.x * gridDim.x;
   for (int i = sstart; i &lt; stop; i += step)
   {
     d[i] = a[i] * Math.Exp(b[i]) * Math.Exp(c[i]);
   }
 } </code></pre>



<p><br>This function is later called in a&nbsp;<code>Parallel.For</code>&nbsp;construct.</p>



<p>However, Numerics.Vector does not provide a vectorized exponential function. Therefore, we have to write our own:</p>



<pre class="wp-block-code"><code lang="csharp" class="language-csharp"> [IntrinsicFunction("hybridizer::exp")]
 [MethodImpl(MethodImplOptions.AggressiveInlining)]
 public static Vector&lt;double> Exp(Vector&lt;double> x)
 {
   double[] tmp = new double[Vector&lt;double>.Count];
   for(int k = 0; k &lt; Vector&lt;double>.Count; ++k)
   {
     tmp[k] = Math.Exp(x[k]);
   }
   return new Vector&lt;double>(tmp);
 } </code></pre>



<p>As a glance, we can see the problems: each exponential will first break the AVX context (<a href="https://software.intel.com/en-us/articles/avoiding-avx-sse-transition-penalties">which cost tens of cycles</a>), and trigger 4 function calls instead of one.</p>



<p>With no surprise, this code performs really badly:</p>



<figure class="wp-block-table"><table><tbody><tr><td>Flavor</td><td>Scalar C#</td><td>Vector C#</td><td>Vector Hyb</td><td>Scalar Hyb</td></tr><tr><td>GB/s</td><td>13.42</td><td>1.80</td><td>14.91</td><td>14.13</td></tr></tbody></table></figure>



<div class="wp-block-image"><figure class="aligncenter"><a href="http://www.altimesh.com/wp-content/uploads/2017/06/bandwidth-numerics-vector-speedup.png" class="fancyboxgroup" rel="gallery-3339"><img decoding="async" src="http://hybridizer.io/wp-content/uploads/2017/06/bandwidth-numerics-vector-speedup.png" alt="" class="wp-image-242"/></a></figure></div>



<p>If we look at the generated assembly, it confirms what we suspected (context switched, and ymm register splitting):</p>



<pre class="wp-block-code"><code class=""> vextractf128 xmm9,ymm6,1
 vextractf128 xmm10,ymm7,1
 vextractf128 xmm11,ymm8,1
 call 00007FF8127C6B80 // exp
 vinsertf128 ymm8,ymm8,xmm11,1
 vinsertf128 ymm7,ymm7,xmm10,1
 vinsertf128 ymm6,ymm6,xmm9,1 </code></pre>



<h2 class="wp-block-heading">Branching</h2>



<p>Branch are expressed using&nbsp;<code>if</code>&nbsp;or ternary operators in scalar code. However, those are not available in Numerics.Vector, since the code is manually vectorized.<br>Branches must be expressed using&nbsp;<code>ConditionalSelect</code>, which leads to code:</p>



<pre class="wp-block-code"><code lang="csharp" class="language-csharp"> public static Vector&lt;double> func(Vector&lt;double> x)
 {
   Vector&lt;long> mask = Vector.GreaterThan(x, one);
   Vector&lt;double> result = Vector.ConditionalSelect(mask, x, one);
   return result;
 } </code></pre>



<p>As we can see, expressing conditions with Numerics.Vector is not intuitive, intrusive, and bug prone. It’s actually the same as writing AVX compiler intrinsics in C++. On the other hand, Hybridizer supports conditions, which allow you to write the above code this way:</p>



<pre class="wp-block-code"><code lang="csharp" class="language-csharp"> [Kernel]
 public static double func(double x)
 {
   if (x > 1.0)
     return x;
   return 1.0;
 } </code></pre>



<h2 class="wp-block-heading">Conclusion</h2>



<p>Numerics.Vector gives easily reasonable performances on simple code (no branches, no function calls). Speed-up is what we expect (vector unit width) on simple code. However, it’s time-consuming and error-prone to express conditions, and performance is completely broken as soon as some Jitter Intrinsic is missing (such as exponential).</p>



<p></p>



<p class="has-cyan-bluish-gray-color has-text-color"></p><p>The post <a href="https://blog.infine.com/from-c-to-simd-numerics-vector-and-hybridizer-3339">From C# to SIMD : Numerics.Vector and Hybridizer</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/from-c-to-simd-numerics-vector-and-hybridizer-3339/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Prise en main du cache distribué Microsoft AppFabric</title>
		<link>https://blog.infine.com/prise-en-main-du-cache-distribue-microsoft-appfabric-2040?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=prise-en-main-du-cache-distribue-microsoft-appfabric</link>
					<comments>https://blog.infine.com/prise-en-main-du-cache-distribue-microsoft-appfabric-2040#comments</comments>
		
		<dc:creator><![CDATA[Grégory Ghez]]></dc:creator>
		<pubDate>Wed, 03 Oct 2012 10:03:00 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[AppFabric]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Cache Distribué]]></category>
		<category><![CDATA[Cluster]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[NuGet]]></category>
		<category><![CDATA[Velocity]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=2040</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">8</span> <span class="rt-label rt-postfix">min.</span></span> Microsoft AppFabric, anciennement nommé Velocity dans ses versions beta, est un cache distribué. Pour schématiser, il s&#8217;agit d&#8217;une HashTable partagée via une connectivité réseau. Dans son produit, Microsoft propose une utilisation sous la forme d&#8217;un cluster d&#8217;hôtes permettant ainsi une montée en charge facile d&#8217;installation. Parmi les fonctionnalités proposées : Support d&#8217;un nombre de serveurs allant &#8230;</p>
<p>The post <a href="https://blog.infine.com/prise-en-main-du-cache-distribue-microsoft-appfabric-2040">Prise en main du cache distribué Microsoft AppFabric</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">8</span> <span class="rt-label rt-postfix">min.</span></span><strong>Microsoft AppFabric</strong>, anciennement nommé <strong>Velocity</strong> dans ses versions beta, est un cache distribué. Pour schématiser, il s&#8217;agit d&#8217;une <em><strong>HashTable</strong></em> partagée via une connectivité réseau.</p>
<p>Dans son produit, Microsoft propose une utilisation sous la forme d&#8217;un cluster d&#8217;hôtes permettant ainsi une montée en charge facile d&#8217;installation. Parmi les fonctionnalités proposées :</p>
<ul>
<li>Support d&#8217;un nombre de serveurs allant de 2 à plus d&#8217;une centaine</li>
<li>Redimensionnement dynamique du cluster (ajout/suppression de noeuds) sans interruption de service</li>
<li>Load-balancing automatique : le service distribue de manière autonome les travaux aux différents noeuds du cluster</li>
<li>Haute disponibilité : les données sont répliquées sur les hôtes du cluster</li>
<li>Intégration des sessions ASP.NET</li>
</ul>
<p>L&#8217;API permettant la consommation du cache AppFabric se veut extrêmement épurée. Il en résulte une prise en main rapide et une mise en place peu coûteuse en temps.</p>
<p>Enfin, le serveur ainsi que l&#8217;API client sont disponibles gratuitement au téléchargement. Vous pouvez suivre les liens présents dans la suite de l&#8217;article.<span id="more-2040"></span></p>
<h2>Installation</h2>
<h3>Serveur</h3>
<p>Pour commencer, il faudra télécharger l’installer disponible sur le site de téléchargement de Microsoft à cette adresse : <a href="http://www.microsoft.com/fr-fr/download/details.aspx?id=27115">http://www.microsoft.com/fr-fr/download/details.aspx?id=27115</a></p>
<p><em>L’installer fait environ 30 Mo, et la version utilisé dans cet article est la 1.1.0.0</em></p>
<p>Voici le premier écran d’installation :</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/AppFabric-1.1-for-Windows-Server-Setup-Wizard_1.jpg" class="fancyboxgroup" rel="gallery-2040"><img fetchpriority="high" decoding="async" class="aligncenter size-medium wp-image-2081" src="https://blog.infine.com/wp-content/uploads/2012/09/AppFabric-1.1-for-Windows-Server-Setup-Wizard_1-300x225.jpg" alt="" width="300" height="225" srcset="https://blog.infine.com/wp-content/uploads/2012/09/AppFabric-1.1-for-Windows-Server-Setup-Wizard_1-300x225.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/09/AppFabric-1.1-for-Windows-Server-Setup-Wizard_1.jpg 622w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Passez les étapes et effectuez une installation complète, afin d’éviter de devoir relancer l’installer dans le futur.</p>
<p>Une fois installé, l’outil de configuration de AppFabric Server se lance. Passez les étapes jusqu’à cet écran:<a href="https://blog.infine.com/wp-content/uploads/2012/09/screen-2.png" class="fancyboxgroup" rel="gallery-2040"><img decoding="async" class="aligncenter size-medium wp-image-2086" src="https://blog.infine.com/wp-content/uploads/2012/09/screen-2-300x226.png" alt="" width="300" height="226" srcset="https://blog.infine.com/wp-content/uploads/2012/09/screen-2-300x226.png 300w, https://blog.infine.com/wp-content/uploads/2012/09/screen-2.png 628w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Sans oublier de configurer la base de données en cliquant sur le bouton “Configure”. Veillez à ne pas donner un nom de base de données déjà existant, l’outil se charge de la créer et de la remplir.</p>
<p>Notez également qu’il vous est offert la possibilité de sauvegarder la configuration du serveur dans un fichier XML,  selon vos préférences.</p>
<p>Laissez les pots de communication par défaut, sauf nécessité réseau particulière.</p>
<p>Une fois l&#8217;installation terminée, vous pourrez constater la présence de 3 nouveaux services Windows dans le gestionnaire de services :</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/Services.jpg" class="fancyboxgroup" rel="gallery-2040"><img decoding="async" class="aligncenter size-medium wp-image-2052" src="https://blog.infine.com/wp-content/uploads/2012/09/Services-300x25.jpg" alt="" width="300" height="25" srcset="https://blog.infine.com/wp-content/uploads/2012/09/Services-300x25.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/09/Services.jpg 809w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Ainsi qu’une nouvelle section dans le IIS Manager permettant de monitorer le serveur AppFabric:</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/Internet-Information-Services-IIS-Manager.jpg" class="fancyboxgroup" rel="gallery-2040"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-2061" src="https://blog.infine.com/wp-content/uploads/2012/09/Internet-Information-Services-IIS-Manager-300x91.jpg" alt="" width="300" height="91" srcset="https://blog.infine.com/wp-content/uploads/2012/09/Internet-Information-Services-IIS-Manager-300x91.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/09/Internet-Information-Services-IIS-Manager.jpg 418w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<h2>Outil d’administration du cache</h2>
<p>Il n’y a pas d’outil d’administration fourni avec le serveur, mais vous pouvez télécharger par exemple AppFabric Caching Admin Tool (<a href="http://mdcadmintool.codeplex.com/">http://mdcadmintool.codeplex.com/</a>).</p>
<p>L’outil est à copier dans un dossier, il suffit de lancer le .exe :</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/admin-tool.png" class="fancyboxgroup" rel="gallery-2040"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-2089" src="https://blog.infine.com/wp-content/uploads/2012/09/admin-tool-300x94.png" alt="" width="300" height="94" srcset="https://blog.infine.com/wp-content/uploads/2012/09/admin-tool-300x94.png 300w, https://blog.infine.com/wp-content/uploads/2012/09/admin-tool.png 420w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Une fois l’outil lancé, sur notre serveur AppFabric nouvellement installé, vous pourrez constater la présence de l’hôte principal (sur la machine locale) ainsi que la liste des caches qu’il contient :</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/Microsoft-Distributed-Cache-MDC-Admin-Tool.jpg" class="fancyboxgroup" rel="gallery-2040"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-2068" src="https://blog.infine.com/wp-content/uploads/2012/09/Microsoft-Distributed-Cache-MDC-Admin-Tool-300x200.jpg" alt="" width="300" height="200" srcset="https://blog.infine.com/wp-content/uploads/2012/09/Microsoft-Distributed-Cache-MDC-Admin-Tool-300x200.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/09/Microsoft-Distributed-Cache-MDC-Admin-Tool.jpg 900w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Nous allons créer un cache autre que celui créé par défaut pour les besoins des exemples d’utilisation du cache qui vont suivre.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2069" src="https://blog.infine.com/wp-content/uploads/2012/09/New-Cache-Name.jpg" alt="" width="300" height="280" /></p>
<p>Notez bien que j’ai volontairement activé les notifications, afin de pouvoir utiliser ce mécanisme dans la dernière démonstration.</p>
<p>Créez également 2 régions dans ce cache : “RegionA” (sans eviction) et “RegionB” (avec éviction). Nous reviendrons plus tard sur ce paramètre.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2072" src="https://blog.infine.com/wp-content/uploads/2012/09/Add-Region.jpg" alt="" width="260" height="170" /></p>
<p><span style="color: #ff0000"><strong>Si vous rencontrez des difficultés lors de la création de nouveaux caches ou bien de régions, vérifiez que le service “Remote Registry” sur votre machine (celle où se trouve le serveur AppFabric) est lancé.</strong></span></p>
<p>Définissons désormais les droits d’accès au cache pour l’utilisateur qui consommera ce dernier. Pour ce faire, cliquez sur le noeud racine “Cluster : AppFabric” puis sur le bouton “Security” en haut à droite. Dans la fenêtre de saisie, entrez le nom de l’utilisateur sous la forme : “DOMAIN\user”, c’est tout.</p>
<h3>Client</h3>
<p>La plus simple façon d’installer les assemblies client pour AppFabric est de passer par le gestionnaire de packages NuGet. Si vous ne l’avez pas installé, c’est simple :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2053" src="https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio.jpg" alt="" width="359" height="311" srcset="https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio.jpg 359w, https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio-300x259.jpg 300w" sizes="(max-width: 359px) 100vw, 359px" /></p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/Extension-Manager.jpg" class="fancyboxgroup" rel="gallery-2040"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-2054" src="https://blog.infine.com/wp-content/uploads/2012/09/Extension-Manager-300x207.jpg" alt="" width="300" height="207" srcset="https://blog.infine.com/wp-content/uploads/2012/09/Extension-Manager-300x207.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/09/Extension-Manager.jpg 955w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Dans la capture d’écran ci-dessus, NuGet est déjà installé, le cas contraire un bouton “Install” est disponible.</p>
<p>Une fois cet outil installé, il suffit de taper dans la console NuGet la ligne de commande d’installation du client AppFabric (<a href="http://nuget.org/packages/ServerAppFabric.Client">http://nuget.org/packages/ServerAppFabric.Client</a>) :</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture.jpg" class="fancyboxgroup" rel="gallery-2040"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-2055" src="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-300x97.jpg" alt="" width="300" height="97" srcset="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-300x97.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture.jpg 571w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Pour afficher cette console :</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio_2.jpg" class="fancyboxgroup" rel="gallery-2040"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-2056" src="https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio_2-300x134.jpg" alt="" width="300" height="134" srcset="https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio_2-300x134.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio_2.jpg 650w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<h2>Utilisation</h2>
<p>Nous allons pour ce faire créer une application Console. Si vous avez utilisé NuGet pour obtenir votre package AppFabric client, les références aux assemblies d’AppFabric sont déjà rajoutées à la solution, dans le cas contraire, ajoutez manuellement ces dernières, comme sur cet exemple :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2057" src="https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio_4.jpg" alt="" width="340" height="320" srcset="https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio_4.jpg 340w, https://blog.infine.com/wp-content/uploads/2012/09/ConsoleApplication2-Microsoft-Visual-Studio_4-300x282.jpg 300w" sizes="(max-width: 340px) 100vw, 340px" /></p>
<p>Placez ensuite un fichier App.config à la racine du projet contenant au minimum ceci :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;configuration&gt;
  &lt;configSections&gt;
    &lt;section
        name=&quot;dataCacheClient&quot;
        type=&quot;Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&quot;
        allowLocation=&quot;true&quot;
        allowDefinition=&quot;Everywhere&quot; /&gt;
  &lt;/configSections&gt;
  &lt;dataCacheClient&gt;
    &lt;hosts&gt;
      &lt;host name=&quot;localhost&quot; cachePort=&quot;22233&quot;/&gt;
    &lt;/hosts&gt;
    &lt;clientNotification pollInterval=&quot;1&quot; /&gt;
  &lt;/dataCacheClient&gt;
  &lt;startup&gt;&lt;supportedRuntime version=&quot;v4.0&quot; sku=&quot;.NETFramework,Version=v4.0&quot;/&gt;&lt;/startup&gt;
&lt;/configuration&gt;
</pre>
<p>Remplacez bien entendu “localhost” par le nom d’hôte qui correspond à votre installation et le port par celui que vous avez configuré (22233 est le port par défaut). J’ai également défini le “pollInterval” (délai entre deux notifications) à 1 seconde au lieu de 300s par défaut. <span style="color: #ff0000"><strong>Attention ici il s’agit bien ici de secondes et non de millisecondes.</strong></span></p>
<h3>Premiers pas</h3>
<p>L’exemple ci-dessous illustre la durée de rétention du cache appliquée aux objets stockés :</p>
<pre class="brush: csharp; title: ; notranslate">
static void TestBasicExpiration()
{
    var factory = new DataCacheFactory();
    var cache = factory.GetDefaultCache();

    cache.Put(&quot;obj&quot;, new object(), TimeSpan.FromSeconds(5));

    var timer = new Timer(new TimerCallback(o =&gt;
    {
        Console.WriteLine(&quot;obj : {0}&quot;, cache.Get(&quot;obj&quot;));
    }), null, 0, 1000);
}
</pre>
<p>La sortie console est la suivante :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2075" src="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_3.jpg" alt="" width="450" height="164" srcset="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_3.jpg 450w, https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_3-300x109.jpg 300w" sizes="(max-width: 450px) 100vw, 450px" /></p>
<p>Une fois passées les 5 secondes définies comme durée de persistance pour l’objet portant la clé “obj”, ce dernier est détruit et l’appel la clé “obj” ne renvoie plus rien.</p>
<p>Les deux ligne suivantes peuvent être isolées afin de ne pas avoir à redemander ces informations statiques à chaque requête d’objets du cache :</p>
<pre>var factory = new DataCacheFactory();
var cache = factory.GetDefaultCache();</pre>
<p><strong><em>GetDefaultCache</em></strong> renvoie, comme son nom l’indique, le cache par défaut de l’hôte AppFabric. Pour accéder à un cache nommé, il suffit de remplacer cet appel par <strong><em>GetCache(</em></strong><em>“InfineCache”<strong>)</strong></em> par exemple.</p>
<h3>Utilisation des régions</h3>
<p>Il est possible de stocker des objets dans le cache sous différentes régions :</p>
<pre class="brush: csharp; title: ; notranslate">
static void TestRegion()
{
    var factory = new DataCacheFactory();
    var cache = factory.GetCache(&quot;InfineGroup&quot;);

    cache.Put(&quot;int&quot;, 5);
    cache.Put(&quot;int&quot;, 6, &quot;RegionA&quot;);
    cache.Put(&quot;int&quot;, 7, &quot;RegionB&quot;);

    Console.WriteLine(&quot;int(no region) : {0}&quot;, cache.Get(&quot;int&quot;));
    Console.WriteLine(&quot;int(RegionA) : {0}&quot;, cache.Get(&quot;int&quot;, &quot;RegionA&quot;));
    Console.WriteLine(&quot;int(RegionB) : {0}&quot;, cache.Get(&quot;int&quot;, &quot;RegionB&quot;));
}
</pre>
<h3>Les notifications</h3>
<p>Le système de notification de AppFabric est basé sur l’attachement d’un delegate à un ensemble de filtres d’opérations. Il est possible de s’attacher au cache, à une région du cache ou bien à une clé d’objet précise.</p>
<p>Voici l’exemple :</p>
<pre class="brush: csharp; title: ; notranslate">
static void CacheUpdated(string cacheName, string region, string key,
DataCacheItemVersion version, DataCacheOperations operation,
DataCacheNotificationDescriptor descriptor)
{
    //display some of the delegate parameters
    Console.WriteLine(&quot;A cache-level notification was triggered!&quot;);
    Console.WriteLine(&quot;    Cache: &quot; + cacheName);
    Console.WriteLine(&quot;    Region: &quot; + region);
    Console.WriteLine(&quot;    Key: &quot; + key);
    Console.WriteLine(&quot;    Operation: &quot; + operation);
    Console.WriteLine(&quot;======================================================&quot;);
}

static void TestNotifications()
{
    var factory = new DataCacheFactory();
    var cache = factory.GetCache(&quot;InfineGroup&quot;);

    var rnd = new Random();
    cache.Put(&quot;int&quot;, rnd.Next());

    var allCacheOperations = DataCacheOperations.AddItem | DataCacheOperations.ReplaceItem |
        DataCacheOperations.RemoveItem | DataCacheOperations.CreateRegion |
        DataCacheOperations.ClearRegion | DataCacheOperations.RemoveRegion;

    cache.AddCacheLevelCallback(allCacheOperations,
            new DataCacheNotificationCallback(CacheUpdated));

    cache.Remove(&quot;int&quot;);
    cache.Put(&quot;int&quot;, rnd.Next());
    cache.Put(&quot;int&quot;, rnd.Next());
}
</pre>
<p>Et la sortie résultante :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2076" src="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-2.jpg" alt="" width="491" height="276" srcset="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-2.jpg 491w, https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-2-300x168.jpg 300w" sizes="(max-width: 491px) 100vw, 491px" /></p>
<h3>Opérations Bulk</h3>
<p>Les opérations de type “Bulk” dans AppFabric se limitent à la lecture, il n’y a pour le moment aucun moyen d’effectuer des écritures de masse dans le cache.</p>
<p>La lecture se fait grâce à l’instruction <strong><em>BulkGet</em></strong> de l’objet <strong><em>DataCache</em></strong> :</p>
<pre class="brush: csharp; title: ; notranslate">
static void TestBulkGet()
{
    var factory = new DataCacheFactory();
    var cache = factory.GetCache(&quot;InfineGroup&quot;);

    cache.CreateRegion(&quot;Desk&quot;);

    var rnd = new Random();
    for (var i = 0; i &lt; 1000; i++)
    {
        cache.Put(&quot;int-&quot; + i, rnd.Next(), &quot;Desk&quot;);
    }

    var gets = cache.BulkGet(new&#x5B;] { &quot;int-6&quot;, &quot;int-14&quot;, &quot;int-578&quot;, &quot;int-988&quot; }, &quot;Desk&quot;);
    foreach (var value in gets)
    {
        Console.WriteLine(&quot;{0} = {1}&quot;, value.Key, value.Value);
    }
}
</pre>
<p>Résultat :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2077" src="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_2-2.jpg" alt="" width="353" height="122" srcset="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_2-2.jpg 353w, https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_2-2-300x103.jpg 300w" sizes="(max-width: 353px) 100vw, 353px" /></p>
<h3>Lock / Unlock</h3>
<p>Il est possible de vérouiller une donnée du cache pour une durée spécifique au moment où on la récupère via l’instruction <strong><em>GetAndLock</em></strong> de l’objet <strong><em>DataCache</em></strong> . Attention cependant, un appel <strong><em>Put</em></strong> sur la clé de l’objet réinitialisera le verrou. De même, un appel à <strong><em>Get</em></strong> ne générera pas d’exception, car ce dernier ne demande pas d’autorisation sur la clé comme le fait <strong><em>GetAndLock</em></strong>.</p>
<p>L’utilisation de <strong><em>GetAndLock</em></strong> combiné avec <strong><em>PutAndUnlock</em></strong> peut s’apparenter à l’utilisation de verrou dans un système multithreading, à la différence que les verrous persistent sur le cache distribué et non sur la machine exécutant le code. <strong>Les verrous sont donc communs à tous les utilisateurs du cache.</strong></p>
<p>Illustration :</p>
<pre class="brush: csharp; title: ; notranslate">
static void TestLock()
{
    var factory = new DataCacheFactory();
    var cache = factory.GetCache(&quot;InfineGroup&quot;);

    cache.Put(&quot;int&quot;, 5);

    DataCacheLockHandle lockHandle;
    var value = cache.GetAndLock(&quot;int&quot;, TimeSpan.FromSeconds(5), out lockHandle);
    Console.WriteLine(&quot;GetAndLock: int = {0}&quot;, value);

    try
    {
        value = cache.GetAndLock(&quot;int&quot;, TimeSpan.FromSeconds(5), out lockHandle);
        Console.WriteLine(&quot;GetAndLock: int = {0}&quot;, value);
    }
    catch (DataCacheException ex)
    {
        if (ex.ErrorCode == DataCacheErrorCode.ObjectLocked)
            Console.WriteLine(&quot;GetAndLock failed, object already locked.&quot;);
        else
            throw ex;
    }

    var timer = new Timer(new TimerCallback(o =&gt;
    {
        Console.WriteLine(&quot;GetAndLock(after 6s): int = {0}&quot;, cache.GetAndLock(&quot;int&quot;, TimeSpan.FromSeconds(5), out lockHandle));
    }), null, 6000, Timeout.Infinite);
}
</pre>
<p>Sortie :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2078" src="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_3-2.jpg" alt="" width="436" height="126" srcset="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_3-2.jpg 436w, https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_3-2-300x86.jpg 300w" sizes="(max-width: 436px) 100vw, 436px" /></p>
<h3>Information sur un objet du cache</h3>
<p>La fonction <strong><em>GetCacheItem</em></strong> de la classe <strong><em>DataCache</em></strong> renvoie une instance de <strong><em>DataCacheItem</em></strong> regroupant quelques informations sur l’objet mis en cache.</p>
<pre class="brush: csharp; title: ; notranslate">
static void TestCacheItem()
{
    var factory = new DataCacheFactory();
    var cache = factory.GetCache(&quot;InfineGroup&quot;);

    cache.Put(&quot;int&quot;, 5, TimeSpan.FromSeconds(15));

    var item = cache.GetCacheItem(&quot;int&quot;);
    Console.WriteLine(&quot;CacheItem informations :&quot;);

    foreach (var prop in item.GetType().GetProperties())
    {
        Console.WriteLine(&quot;{0} = {1}&quot;, prop.Name, prop.GetValue(item, null));
    }
}
</pre>
<p>Sortie :</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-3.jpg" class="fancyboxgroup" rel="gallery-2040"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-2079" src="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-3-300x80.jpg" alt="" width="300" height="80" srcset="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-3-300x80.jpg 300w, https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture-3.jpg 677w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<h3>Recherche dans le cache</h3>
<p>La recherche dans le cache peut se faire grâce aux méthodes <strong><em>GetObjectsByTag</em></strong>, <strong><em>GetObjectsByAllTags</em></strong>, <strong><em>GetObjectsByAnyTag</em></strong> et <strong><em>GetObjectsInRegion</em></strong>.</p>
<p>Exemple :</p>
<pre class="brush: csharp; title: ; notranslate">
static void TestSearch()
{
    var factory = new DataCacheFactory();
    var cache = factory.GetCache(&quot;InfineGroup&quot;);

    cache.CreateRegion(&quot;Desk&quot;);
    var rnd = new Random();

    for (var i = 0; i &lt; 1000; i++)
    {
        var tagParite = new DataCacheTag(i % 2 == 0 ? &quot;Paire&quot; : &quot;Impaire&quot;);
        var tagRandom = new DataCacheTag(rnd.Next(100).ToString());

        cache.Put(&quot;int-&quot; + i, i, new&#x5B;] { tagParite, tagRandom }, &quot;Desk&quot;);
    }

    foreach (var pair in cache.GetObjectsByTag(new DataCacheTag(&quot;67&quot;), &quot;Desk&quot;))
    {
        var item = cache.GetCacheItem(pair.Key, &quot;Desk&quot;);
        Console.WriteLine(&quot;{0} : {1} &#x5B;Tag: {2}]&quot;, pair.Key, pair.Value, string.Join(&quot;,&quot;, item.Tags));
    }
}
</pre>
<p>Sortie :</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2080" src="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_2-3.jpg" alt="" width="365" height="201" srcset="https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_2-3.jpg 365w, https://blog.infine.com/wp-content/uploads/2012/09/PrtScr-capture_2-3-300x165.jpg 300w" sizes="(max-width: 365px) 100vw, 365px" /></p>
<h2>Ressources</h2>
<p>Examples C# : <a href="https://github.com/gg00xiv/infine/blob/master/AppFabricTests.zip?raw=true">AppFabricTests.zip</a></p>
<p>Liens MSDN :</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ee790941%28v=azure.10%29.aspx">Developing a Cache Client</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ff921012%28v=azure.10%29.aspx">Managing Security</a></li>
</ul><p>The post <a href="https://blog.infine.com/prise-en-main-du-cache-distribue-microsoft-appfabric-2040">Prise en main du cache distribué Microsoft AppFabric</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/prise-en-main-du-cache-distribue-microsoft-appfabric-2040/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Kinect for Windows SDK: Released!</title>
		<link>https://blog.infine.com/kinect-for-windows-sdk-released-947?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=kinect-for-windows-sdk-released</link>
					<comments>https://blog.infine.com/kinect-for-windows-sdk-released-947#respond</comments>
		
		<dc:creator><![CDATA[David Taing]]></dc:creator>
		<pubDate>Tue, 21 Jun 2011 12:52:48 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Kinect]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[SDK]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=947</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">2</span> <span class="rt-label rt-postfix">min.</span></span> Dévoilé durant le MIX11 qui s'est déroulé à Las Vegas en avril, c'est finalement à la date du 16 juin 2011 que Microsoft a décidé de mettre à disposition le kit de développement (SDK) Kinect pour Windows. Les développeurs en herbe ou passionnés peuvent désormais se donner à coeur joie dans la conception d'applications exploitant les fonctionnalités interactives de la machine. Espérons voir fleurir rapidement sur la toile bon nombre d'outils qui sauront tirer partie de ce petit bijou technologique !</p>
<p>The post <a href="https://blog.infine.com/kinect-for-windows-sdk-released-947">Kinect for Windows SDK: Released!</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">2</span> <span class="rt-label rt-postfix">min.</span></span>Dévoilé durant le MIX11 qui s&#8217;est déroulé à Las Vegas en avril dernier, c&#8217;est finalement à la date du 16 juin 2011 que Microsoft a décidé de mettre à disposition le kit de développement (SDK) Kinect pour Windows. Les développeurs en herbe ou passionnés peuvent désormais se donner à coeur joie dans la conception d&#8217;applications exploitant les fonctionnalités interactives de la machine. Espérons voir fleurir rapidement sur la toile bon nombre d&#8217;outils qui sauront tirer partie de ce petit bijou technologique !</p>
<p><figure id="attachment_952" aria-describedby="caption-attachment-952" style="width: 300px" class="wp-caption aligncenter"><a href="https://blog.infine.com/wp-content/uploads/2011/06/SDK-Kinect-windows.jpg" class="fancyboxgroup" rel="gallery-947"><img loading="lazy" decoding="async" class="size-full wp-image-952" src="https://blog.infine.com/wp-content/uploads/2011/06/SDK-Kinect-windows.jpg" alt="Kinect pour Windows" width="300" height="245" /></a><figcaption id="caption-attachment-952" class="wp-caption-text">Sortie du SDK Kinect pour Windows</figcaption></figure></p>
<p>Initialement dénommé &#8220;Project Natal&#8221;, le Kinect possède désormais une place d&#8217;honneur dans le World Guiness Book comme étant l'&#8221;accessoire High-Tech le plus vendu dans un court laps de temps&#8221; (dixit. World Guiness Book). Initialement conçu pour la console de Microsoft, la Xbox 360, le Kinect s&#8217;est voulu être une nouvelle façon de jouer aux jeux vidéos sans manettes appelé également <em>Motion Gaming</em>. Il a rapidement réussi à attiser la sympathie du public avec son concept de commande à la fois ludique et innovante et offrant alors de nouvelles possibilités en terme d&#8217;intéractions. Disposant de deux caméras, un capteur de champ par infra-rouge et d&#8217;un microphone, le Kinect fonctionne par reconnaissance spatiale d&#8217;un corps en mouvement.</p>
<p>Mais les curieux n&#8217;avaient pas attendu cette sortie pour mettre au point un pilote compatible Windows pour faire leurs premiers essais. C&#8217;est ainsi que le kit <a title="CL-NUI Platform" href="http://codelaboratories.com/nui">CL-NUI Platform</a> a sévi sur internet et proposait déjà de prendre le contrôle sur les capteurs vidéos de l&#8217;appareil. On a pu voir apparaître quelques démos techniques (des exemples sur <a title="Kinect Hack" href="http://kinecthacks.net/">http://kinecthacks.net/</a>) prenant en compte la détection de mouvements qui laisse présager d&#8217;autres innovations dans la conception d&#8217;interfaces interractives différentes du mythique combo clavier/souris ou plus récemment écran tactile : robotique, réalité augmenté, &#8230; Minority Report, ça vous rappelle des souvenirs ?</p>
<p><span id="more-947"></span></p>
<p><strong>Prérequis:</strong><br />
<strong> Matériel</strong></p>
<ul>
<li>Dispositif Kinect pour Xbox 360</li>
<li>PC avec processeur dual-core, 2.66-GHz ou plus</li>
<li>Windows 7–carte graphique compatible DirectX® 9.0c</li>
<li>2-Go RAM (4-Go RAM recommandé)</li>
</ul>
<p><strong>Logiciel</strong></p>
<ul>
<li>Windows 7 (x86 ou x64)</li>
<li><a href="http://www.microsoft.com/express/downloads/">Visual Studio 2010 Express</a> (ou autre édition 2010)</li>
<li><a href="http://msdn.microsoft.com/en-us/netframework/aa569263">Microsoft .NET Framework 4.0</a></li>
</ul>
<p><strong>Et pour bien commencer&#8230;</strong></p>
<p><span style="text-decoration: underline">En C#</span></p>
<p>Avec votre Visual Studio préféré, ajouter la référence &#8220;Microsoft.Research.Kinect&#8221; depuis la GAC (Global Assembly Cache) et appeler l&#8217;assembly dans vos codes projets.</p>
<p>Pour l&#8217;API NUI<br />
using Microsoft.Research.Kinect.Nui</p>
<p>Pour l&#8217;API Audio<br />
using Microsoft.Research.Kinect.Audio<br />
<span style="text-decoration: underline"> </span></p>
<p><span style="text-decoration: underline">En C++</span></p>
<ul>
<li>Ne pas compiler vos projets C++ avec w_char comme type de séparateur.</li>
<li>Pour utiliser l&#8217;API NUI, faire un include de MSR_NuiApi.h.<br />
Localisation : Program Files\Microsoft Research KinectSDK\inc</li>
<li>Pour utiliser l&#8217;API Kinect Audio, faire un include de MSRKinectAudio.h.<br />
Localisation : Program Files\Microsoft Research KinectSDK\inc</li>
<li>Faire le lien vers MSRKinectNUI.lib.<br />
Localisation :  Program Files\Microsoft Research KinectSDK\lib</li>
<li>Enfin, s&#8217;assurer que les dlls du SDK de Kinect sont présents dans le bon répertoire lors de l&#8217;exécution du projet.<br />
Localisation: Program Files\Microsoft Research KinectSD</li>
</ul>
<p>Pour plus de détails, je vous recommande de lire la documentation fournie avec le kit de développement (<a title="Documentation SDK Kinect" href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/docs/ProgrammingGuide_KinectSDK.pdf">disponible ici</a>) ainsi que de vous appuyer sur les différentes applications démos présentes dans le répertoire &#8220;Mes documents\Microsoft Research KinectSDK Samples&#8221;.</p>
<p>Have fun <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p style="text-align: center"><a title="Télécharger le SDK Kinect for Windows" href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/" target="_blank">Télécharger le SDK Kinect for Windows</a></p><p>The post <a href="https://blog.infine.com/kinect-for-windows-sdk-released-947">Kinect for Windows SDK: Released!</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/kinect-for-windows-sdk-released-947/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WPF &#038; Silverlight : L’état de l’art au Microsoft TechDays 2011 (partie 2)</title>
		<link>https://blog.infine.com/wpf-silverlight-l%e2%80%99etat-de-l%e2%80%99art-au-microsoft-techdays-2011-partie-2-663?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wpf-silverlight-l%25e2%2580%2599etat-de-l%25e2%2580%2599art-au-microsoft-techdays-2011-partie-2</link>
					<comments>https://blog.infine.com/wpf-silverlight-l%e2%80%99etat-de-l%e2%80%99art-au-microsoft-techdays-2011-partie-2-663#respond</comments>
		
		<dc:creator><![CDATA[David Taing]]></dc:creator>
		<pubDate>Tue, 05 Apr 2011 15:00:56 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Conférence]]></category>
		<category><![CDATA[Blend SDK]]></category>
		<category><![CDATA[Command]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[Microsoft Techdays 2011]]></category>
		<category><![CDATA[MVVM]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=663</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">5</span> <span class="rt-label rt-postfix">min.</span></span> Accéder à la partie 1 Après une première partie qui s&#8217;est concentrée sur l&#8217;organisation d&#8217;un projet WPF/Silverlight, attaquons-nous à quelque chose de plus compliqué avec les techniques avancées&#8230; Silverlight et WPF en entreprise : retours d&#8217;expérience, bonnes pratiques et techniques avancées par Luc Vo Van (Microsoft Services) et Thomas Lebrun (Access-IT) Architecture type WPF et &#8230;</p>
<p>The post <a href="https://blog.infine.com/wpf-silverlight-l%e2%80%99etat-de-l%e2%80%99art-au-microsoft-techdays-2011-partie-2-663">WPF & Silverlight : L’état de l’art au Microsoft TechDays 2011 (partie 2)</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">5</span> <span class="rt-label rt-postfix">min.</span></span><a href="https://blog.infine.com/wpf-silverlight-letat-de-lart-au-microsoft-techdays-2011-partie-1-595">Accéder à la partie 1</a></p>
<p><em>Après une première partie qui s&#8217;est concentrée sur l&#8217;organisation d&#8217;un projet WPF/Silverlight, attaquons-nous à quelque chose de plus compliqué avec les techniques avancées&#8230;</em></p>
<h2>Silverlight et WPF en entreprise : retours d&#8217;expérience, bonnes pratiques et techniques avancées par Luc Vo Van (Microsoft Services) et Thomas Lebrun (Access-IT)</h2>
<h3><span style="text-decoration: underline">Architecture type</span></h3>
<p>WPF et Silverlight nous offrent la possibilité de développer des applications composites. Le pattern Models-Views-ViewModels <em>dit MVVM</em> est favorisé.<br />
<img loading="lazy" decoding="async" class="aligncenter size-full wp-image-685" src="https://blog.infine.com/wp-content/uploads/2011/03/archi.jpg" alt="" width="720" height="428" srcset="https://blog.infine.com/wp-content/uploads/2011/03/archi.jpg 720w, https://blog.infine.com/wp-content/uploads/2011/03/archi-300x178.jpg 300w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<p><span id="more-663"></span></p>
<h3><span style="text-decoration: underline">Principes fondamentaux</span></h3>
<h4>Composition</h4>
<p>Développer une application par composition c’est créer une coquille vide à laquelle vient se greffer différents modules applicatifs  indépendants qui interagissent ensemble pour les besoins de notre application. Le principal intérêt de ce type d’application est qu’il est possible de paralléliser les développements. En effet, puisque chaque module est indépendant, il est simple de regrouper les équipes en unités fonctionnelles. Ces unités fournissent alors aux autres équipes l’interface de leur implémentation ce qui permet d’exécuter toute l’application même si le développement d’un module n’est pas totalement finalisé.</p>
<p>Avec ce mécanisme, il est alors très aisé d’activer ou de désactiver une fonctionnalité. La maintenabilité de l’application est également largement revue à la hausse grâce au découpage par modules. Chaque module étant cloisonné et hiérarchisé, l’évolution d’un module ne sera visible de l’extérieur qu’à travers son interface. L’impact sur les autres modules est donc fortement limité.</p>
<p>Généralement, on observe deux approches d’architecture de développement par composition</p>
<ul>
<li>Régions + Services, c’est le cas avec le <a href="http://compositewpf.codeplex.com/" target="_blank">Framework Prism</a></li>
<li>Services</li>
</ul>
<h4>Inversion of control</h4>
<p>Plus communément appelé Ioc, l’Inversion of Control est un pattern utilisé pour l’injection de dépendance. On l’appelle  également parfois <em>injection de code</em> car en favorisant un découplage fort entre l’interface (UI) et l’implémentation (UI logic), il facilite la substitution des composants par des mocks lorsqu&#8217;un module n&#8217;est pas encore disponible.</p>
<p>Diverses implémentations sont possibles via <a href="http://unity.codeplex.com/">Unity</a>, <a href="http://www.springframework.net/">Spring .NET</a>, <a href="http://ninject.org/">Ninject</a>…</p>
<h4>Commanding</h4>
<p>Le système de commande est un mécanisme qui permet l’exécution d’actions déclenchées par des contrôles de l’IHM. Par exemple, sur un contrôle de type Button, habituellement, les actions qui suivent le clic sur celui-ci sont codés dans l’événement Click du code behind. Avec le système de commande, on écrit les actions dans la commande et il suffit alors de préciser au bouton le nom de cette commande à exécuter.</p>
<p>Ce mécanisme permet donc de découpler la source de l’action car les actions ne dépendent plus de l’événement Click. Il y a donc peu d’adhérence à l’interface graphique. Autre point fort, une commande peut également être affectée à plusieurs contrôles à la fois.</p>
<p>L’objectif du système de commande est de découpler l’interface graphique du code appelé lors de l’exécution d’une action. Un événement <em>CanExecute</em> intervient dans la définition d’une règle d’activation de la commande. Cette règle, lorsqu’elle est satisfaite active alors les contrôles de l’IHM affectés par cette commande.</p>
<p>Exemple :</p>
<p>//Création de la commande MyCommand<br />
public static RoutedUICommand MyCommand { get; set; }</p>
<p>//Execute : Actions de la commande<br />
private void ShowMessage_Executed(object sender, ExecutedRoutedEventArgs e)<br />
{<br />
MessageBox.Show(&#8220;Hello world&#8221;);<br />
}</p>
<p>//CanExecute : Condition d&#8217;activation de la commande<br />
private void ShowMessage_CanExecute(object sender, CanExecuteRoutedEventArgs e)<br />
{<br />
if(condition)<br />
e.CanExecute = true;<br />
}</p>
<p>//Dans le construteur, on enregistre les événements Executed et CanExecute<br />
CommandBinding myBinding = new CommandBinding(MyCommand);<br />
myBinding.CanExecute += ShowMessage_CanExecute;<br />
myBinding.Executed += ShowMessage_Executed;<br />
CommandBindings.Add(myBinding);</p>
<p>MVVM :</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- Après avoir inscrit la commande MyCommand au ViewModel et enregistré dans le ViewModel dans le DataContext de la View, on affecte la commande par Binding--&gt;
&lt;Button x:Name=&quot;MyButton&quot; Command=&quot;{Binding MyCommand}&quot; /&gt;
</pre>
<p>Non MVVM :</p>
<p>//Dans le constructeur, on affecte au bouton MyButton la commande MyCommand<br />
myButton.Command = MyCommand;</p>
<h4>Messaging</h4>
<p>Par messaging, on entend l&#8217;implémentation d&#8217;un mécanisme permettant le dialogue entre les modules. Ce mécanisme, appelé Messenger, doit permettre aux modules de publier un événement et de notifier le ou les modules qui y sont abonnés. On parle alors de communication inter-ViewModels. Il est également possible de notifier un service du Shell par cette méthode pour par exemple faire appel au log, etc…</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2011/03/messaging.jpg" class="fancyboxgroup" rel="gallery-663"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-822" src="https://blog.infine.com/wp-content/uploads/2011/03/messaging.jpg" alt="" width="725" height="339" srcset="https://blog.infine.com/wp-content/uploads/2011/03/messaging.jpg 725w, https://blog.infine.com/wp-content/uploads/2011/03/messaging-300x140.jpg 300w" sizes="(max-width: 725px) 100vw, 725px" /></a></p>
<p>On distingue généralement les différents types d’implémentations suivantes :</p>
<ul>
<li>Event agregattor (<a href="http://compositewpf.codeplex.com/" target="_blank">Framework Prism</a>)</li>
<li>Messenger</li>
<li>Queue</li>
</ul>
<h4>Services du Shell</h4>
<p>Les services du Shell regroupent tous les composants qui permettent aux Views, Viewmodels et Controls de communiquer avec l’hôte. Ce sont les services transverses  tels que les Popups Messages, Ribbon Menu, Logging, Workspaces, etc …, et qui peuvent être utilisés à tout instant.</p>
<h3><span style="text-decoration: underline">Approches par patterns:</span></h3>
<p>Avec le pattern MVVM, nous avons vu qu’il existe une séparation forte entre le View et le ViewModel. Cette séparation permet 2 approches :</p>
<ul>
<li><strong>ViewModelFirst</strong> : Dans cette configuration, le ViewModel s’occupe de créer les différents Views et de définir les bindings associés.</li>
<li><strong>ViewFirst</strong> : Dans cette configuration, la View utilise le ViewModel comme ressource. Le binding est alors défini dans la vue. Ce pattern est celui qui est utilisé par le <a href="http://compositewpf.codeplex.com/" target="_blank">Framework Prism</a>.</li>
</ul>
<p>Pour des applications implémentant des formulaires, l’utilisation du <em>ViewState</em> permet de définir l’état d’un formulaire avec des changements d’états plus simples et plus légers. En effet, il suffit de ne créer qu’une seule View qui contient alors les différents états du formulaire. Introduit par Silverlight et désormais présent dans WPF 4.0, le ViewState ajoute également des animations de transitions issues du <a href="http://www.microsoft.com/downloads/fr-fr/details.aspx?displaylang=fr&amp;FamilyID=75e13d71-7c53-4382-9592-6c07c6a00207">Blend SDK</a> à travers l’utilisation de <em>behaviours</em>.</p>
<p>Parfois, il arrive qu’on ait besoin de créer une fonctionnalité supplémentaire pour un contrôle existant. Dans ce cas de figure, nous utilisons alors les <em>Attached Property</em> qui permettent d’étendre un contrôle existant avec notre fonctionnalité, sans avoir à procéder à un héritage.</p>
<h3><span style="text-decoration: underline">Blend SDK:</span></h3>
<p>Ce SDK fournit entre autre des <em>behaviours </em>qui permettent de greffer des  fonctionnalités sur des contrôles pour avoir des comportements supplémentaires.</p>
<ul>
<li><strong>InvokeCommandAction</strong> : Permet de lier un événement à une commande sans envoyer de paramètre.</li>
<li><strong>DataStateBehaviour</strong> : Sélectionne un VisualState en fonction d’une propriété</li>
<li><strong>CallMethodAction</strong> : Permet à un événement d’exécuter une méthode.</li>
</ul>
<p>Pour utiliser ces behaviours, il faut au préalable charger l’assembly System.Window.Interactivity (2 dlls). Il est également possible d’écrire ses propres extensions.</p>
<h3><span style="text-decoration: underline">Testing</span></h3>
<p>Le pattern MVVM d’une manière générale est le pattern de prédilection pour mettre en place des tests unitaires automatisés pour les applications WPF et Silverlight. Nous avons vu auparavant que la mise en place d’un pattern d’IoC facilitait l’écriture de Mocks. Et bien, c’est avec cette même facilité qu’on pourra également mettre en place une série de tests automatisés car l’UI et l’UI logic sont complètement décorrélés dans cette architecture.</p>
<p>Pour réaliser vos tests selon le type d&#8217;application :</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="text-align: center" width="318" valign="top">
<h4>WPF</h4>
</td>
<td style="text-align: center" width="318" valign="top">
<h4>Silverlight</h4>
</td>
</tr>
<tr>
<td width="318" valign="top">Les principaux outils de testing sont déjà intégrés à Visual StudioLe ViewModel est testable avec UnitTesting</p>
<p>La View est testable avec UI Automation</td>
<td width="318" valign="top">Contrairement à WPF, Silverlight ne dispose pas d’outil de test intégré à Visual Studio &#8211; peut-être dans une future version ? -, cependant, les tests unitaires sont réalisables à l’aide de <a href="http://silverlight.codeplex.com/">Silverlight Unit Test Framework</a>.Le ViewModel est testable avec Statlight, Odin, …</td>
</tr>
</tbody>
</table>
<h4><span><span style="text-decoration: underline">Liens externes</span></span></h4>
<p>MVVM : <a href="http://compositewpf.codeplex.com/" target="_blank">Framework Prism</a>, <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyId=bcb166f7-dd16-448b-a152-9845760d9b4c&amp;displaylang=en">Microsoft Enterprise Library</a></p>
<p>Inversion of Control : <a href="http://unity.codeplex.com/">Unity</a>, <a href="http://www.springframework.net/">Framework Spring .NET</a>, <a href="http://ninject.org/">Ninject</a></p>
<p>Behaviour : <a href="http://www.microsoft.com/downloads/fr-fr/details.aspx?displaylang=fr&amp;FamilyID=75e13d71-7c53-4382-9592-6c07c6a00207">Blend SDK</a></p>
<p>Testing : <a href="http://silverlight.codeplex.com/">Silverlight Toolkit (Silverlight Unit Test Framework)</a></p><p>The post <a href="https://blog.infine.com/wpf-silverlight-l%e2%80%99etat-de-l%e2%80%99art-au-microsoft-techdays-2011-partie-2-663">WPF & Silverlight : L’état de l’art au Microsoft TechDays 2011 (partie 2)</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/wpf-silverlight-l%e2%80%99etat-de-l%e2%80%99art-au-microsoft-techdays-2011-partie-2-663/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WPF &#038; Silverlight : L&#8217;état de l&#8217;art au Microsoft TechDays 2011 (partie 1)</title>
		<link>https://blog.infine.com/wpf-silverlight-letat-de-lart-au-microsoft-techdays-2011-partie-1-595?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wpf-silverlight-letat-de-lart-au-microsoft-techdays-2011-partie-1</link>
					<comments>https://blog.infine.com/wpf-silverlight-letat-de-lart-au-microsoft-techdays-2011-partie-1-595#comments</comments>
		
		<dc:creator><![CDATA[David Taing]]></dc:creator>
		<pubDate>Fri, 11 Mar 2011 10:00:07 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Conférence]]></category>
		<category><![CDATA[Ergonomie]]></category>
		<category><![CDATA[Intégration graphique]]></category>
		<category><![CDATA[Microsoft Techdays 2011]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=595</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">3</span> <span class="rt-label rt-postfix">min.</span></span> A chaque événement TechDays, c&#8217;est l&#8217;effervescence au sein de la communauté Microsoft. Pour commencer cette nouvelle année, c&#8217;est le Cloud qui était à l&#8217;honneur. Mais nous allons ici évoquer un sujet un peu moins brumeux et qui, nous, les développeurs .NET, nous concerne plus particulièrement : WPF &#38; Silverlight. A travers une série d&#8217;articles, nous ferons &#8230;</p>
<p>The post <a href="https://blog.infine.com/wpf-silverlight-letat-de-lart-au-microsoft-techdays-2011-partie-1-595">WPF & Silverlight : L’état de l’art au Microsoft TechDays 2011 (partie 1)</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">3</span> <span class="rt-label rt-postfix">min.</span></span><em>A chaque événement TechDays, c&#8217;est l&#8217;effervescence au sein de la communauté Microsoft. Pour commencer cette nouvelle année, c&#8217;est le Cloud qui était à l&#8217;honneur. Mais nous allons ici évoquer un sujet un peu moins brumeux et qui, nous, les développeurs .NET, nous concerne plus particulièrement : <strong>WPF &amp; Silverlight</strong>. </em></p>
<p><em>A travers une série d&#8217;articles, nous ferons le point sur les principales conférences autour de WPF &amp; Silverlight&#8230;</em></p>
<p><em> </em></p>
<h2>Changer la vie de vos utilisateurs en intégrant du design et de l&#8217;ergonomie par Olivier Courtois (Bewise)</h2>
<p>De nos jours, nous avons affaire à des &#8220;superutilisateurs&#8221; qui ont des attentes surdéveloppées. Bien plus que par le passé, les applications doivent se soucier davantage du confort d&#8217;utilisation : on parle alors d’ergonomie. Pour pallier à des surcoûts postproduction, cette réflexion doit être posée en amont.</p>
<p>Le travail général de l&#8217;ergonomie s&#8217;effectue dans le cadre d&#8217;une réflexion centrée autour de l&#8217;utilisateur. Cette réflexion, auprès d&#8217;utilisateurs réels -dans le meilleur des cas- ou auprès d&#8217;utilisateurs fictifs, donne naissance aux exigences ergonomiques.</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2011/02/schema12.png" class="fancyboxgroup" rel="gallery-595"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-627" src="https://blog.infine.com/wp-content/uploads/2011/02/schema12.png" alt="" width="614" height="100" srcset="https://blog.infine.com/wp-content/uploads/2011/02/schema12.png 614w, https://blog.infine.com/wp-content/uploads/2011/02/schema12-300x48.png 300w" sizes="(max-width: 614px) 100vw, 614px" /></a><br />
<span id="more-595"></span><br />
Avec la technologie SilverLight/WPF, la chaîne de travail est occupée autour de 4 postes d&#8217;exécutions clés :</p>
<ul>
<li>Ergonomie</li>
<li>Graphisme</li>
<li>Intégration graphique</li>
<li>Développement</li>
</ul>
<p>Nous allons ici nous intéresser plus particulièrement aux 3 premières étapes de cette chaîne.</p>
<ol>
<h3><span style="text-decoration: underline">Ergonomie</span></h3>
</ol>
<p>L&#8217;ergonomie c&#8217;est l&#8217;art de faire s&#8217;adapter l&#8217;outil à l&#8217;homme à travers une interface. Le rôle de cette étape est de constituer le document de spécification ergonomique.</p>
<p>Le travail sur l’ergonomie est constitué des phases d’exécutions suivantes :</p>
<p>1)      Recueil du besoin : on itère auprès des utilisateurs pour déterminer le fonctionnement général de l’application</p>
<p>2)      Etude de l&#8217;existant (s’il existe !)</p>
<p>3)      Création de croquis</p>
<ul>
<li>Croquis papier : permet d’être plus créatif</li>
<li>Application d’UI Design Pattern</li>
</ul>
<p>4)      Proposition statique</p>
<ul>
<li>Croquis numérique : toujours à l’état de croquis, cette étape permet d’être clair lors de la confrontation avec les utilisateurs.</li>
</ul>
<p>5)      Proposition dynamique</p>
<ul>
<li>Maquette dynamique : avec la mise en place d’interactions dans les croquis numériques, les utilisateurs perçoivent de manière plus évidente le fonctionnement que pourrait donner l’ergonomie de l’application.</li>
<li>Permet de tester auprès des utilisateurs</li>
<li>Permet de valider l&#8217;ergonomie</li>
</ul>
<p>6)      Spécification ergonomique</p>
<ul>
<li>Recommandations ergonomiques</li>
<li>Typologie des utilisateurs</li>
<li>Croquis des principaux écrans</li>
<li>Rationalisation des choix</li>
</ul>
<p>Le travail sur l’ergonomie produit le document de spécification ergonomique, document qui sera par la suite réutilisé au cours de l’intégration graphique.</p>
<ol>
<h3><span style="text-decoration: underline">Graphisme</span></h3>
</ol>
<p>Le graphisme -ou design d’application- doit à travers son esthétisme communiquer visuellement la même information à tous les utilisateurs tout en prolongeant la marque du client. Au final, le design sublime l’ergonomie. Cette étape doit permettre la production de la charte graphique de l’application.</p>
<p>C’est ici qu’intervient un designer dont la tâche est de construire la charte graphique selon les étapes suivantes :</p>
<p>1)      Recueil du besoin</p>
<p>2)      Maquettage</p>
<p>3)      Définition de la charte graphique de l&#8217;application</p>
<ol>
<h3><span style="text-decoration: underline">Intégration graphique</span></h3>
</ol>
<p>L’intégration graphique consiste à créer les écrans de l’application tout en respectant son ergonomie. Cette étape permet notamment de préparer le travail du développeur. Pour ce faire, l’intégrateur graphique doit avoir à sa disposition à la fois le document de spécification ergonomique qui identifie les contrôles visuels et la charte graphique qui définit le style visuel appliqué aux contrôles.</p>
<p>1)      Recueil du besoin</p>
<p>2)      Création des squelettes d&#8217;écrans</p>
<p>3)      Intégration graphique</p>
<p>A l’issu de ce travail, l’intégrateur graphique met à la disposition des développeurs une bibliothèque de composants stylisés qui doit couvrir tous les besoins de l’application.</p>
<ol>
<h3><span style="text-decoration: underline">Gains Utilisateurs</span></h3>
</ol>
<p>La prise en compte de l’ergonomie au sein des applications SL/WPF offre bien des apports sur plusieurs aspects. Tout d’abord au niveau de la conduite de projet, on observe une amélioration de la productivité grâce au séquençage des tâches. Avec une meilleure ergonomie, l’application est beaucoup plus intuitive d’un point de vue utilisateur et donc les besoins en formations sont diminués et une meilleure satisfaction d’utilisation de l’application et l’adhérence des utilisateurs. Et d’une manière générale, on observe une diminution du nombre d’erreurs.</p>
<h3><span style="text-decoration: underline">Conseil aux développeurs qui veulent se lancer dans l&#8217;ergonomie:</span></h3>
<ul>
<li>Faire attention au vocabulaire employé</li>
<li>Ne pas placer ses contrôles n&#8217;importe où</li>
</ul><p>The post <a href="https://blog.infine.com/wpf-silverlight-letat-de-lart-au-microsoft-techdays-2011-partie-1-595">WPF & Silverlight : L’état de l’art au Microsoft TechDays 2011 (partie 1)</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/wpf-silverlight-letat-de-lart-au-microsoft-techdays-2011-partie-1-595/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Détecter les deadlocks en C# / .NET grâce au pattern IDisposable</title>
		<link>https://blog.infine.com/detecter-les-deadlocks-en-c-net-grace-au-pattern-idisposable-427?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=detecter-les-deadlocks-en-c-net-grace-au-pattern-idisposable</link>
					<comments>https://blog.infine.com/detecter-les-deadlocks-en-c-net-grace-au-pattern-idisposable-427#comments</comments>
		
		<dc:creator><![CDATA[Nicolas Lecrique]]></dc:creator>
		<pubDate>Wed, 09 Feb 2011 14:05:24 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[deadlock]]></category>
		<category><![CDATA[Dispose]]></category>
		<category><![CDATA[IDisposable]]></category>
		<category><![CDATA[lock]]></category>
		<category><![CDATA[mutex]]></category>
		<category><![CDATA[RAII]]></category>
		<category><![CDATA[using]]></category>
		<guid isPermaLink="false">https://blog.infine.com/?p=427</guid>

					<description><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">5</span> <span class="rt-label rt-postfix">min.</span></span> Détecter les deadlocks en C# / .NET grâce au pattern IDisposable Si vous êtes développeur en environnement multithread, alors vous vous êtes déjà posé cette question : Où est ce deadlock ? ! Bien sûr, ce deadlock est non-reproductible, il survient chez l’utilisateur, et l’on peut passer des heures à le chercher. Sans jamais être sur &#8230;</p>
<p>The post <a href="https://blog.infine.com/detecter-les-deadlocks-en-c-net-grace-au-pattern-idisposable-427">Détecter les deadlocks en C# / .NET grâce au pattern IDisposable</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span class="rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Temps de lecture : </span> <span class="rt-time">5</span> <span class="rt-label rt-postfix">min.</span></span></p>
<h1>Détecter les deadlocks en C# / .NET grâce au pattern IDisposable<br />
</h1>
<p>Si vous êtes développeur en environnement multithread, alors vous vous êtes déjà posé cette question : Où est ce deadlock ? !</p>
<p>Bien sûr, ce deadlock est non-reproductible, il survient chez l’utilisateur, et l’on peut passer des heures à le chercher. Sans jamais être sur d’avoir trouvé LE deadlock qui pose problème !</p>
<p>Vous trouverez dans ce post un exemple de lock qui a pour objectif de</p>
<ol>
<li>Pouvoir détecter les deadlocks</li>
<li>Proposer une syntaxe claire et concise</li>
<li> Ajouter un overhead minimum en terme de performance à la syntaxe lock C# classique</li>
</ol>
<h2>Petit rappel : qu’est-ce  qu&#8217;un deadlock ?</h2>
<p>Un deadlock (interblocage dans sa version française que personne n’utilise) est la situation dans laquelle 2 threads s’attendent mutuellement. Cas concret :</p>
<ol>
<li>Un thread T1 acquiert une ressource R1</li>
<li>Un thread T2 acquiert une ressource R2</li>
<li>T1 demande la ressource R2</li>
<li>T2 demande la ressource R1</li>
</ol>
<p>Avec un schéma :</p>
<p><a href="https://blog.infine.com/wp-content/uploads/2010/12/deadlock1.jpg" class="fancyboxgroup" rel="gallery-427"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-431" src="https://blog.infine.com/wp-content/uploads/2010/12/deadlock1.jpg" alt="" width="800" height="600" srcset="https://blog.infine.com/wp-content/uploads/2010/12/deadlock1.jpg 960w, https://blog.infine.com/wp-content/uploads/2010/12/deadlock1-300x225.jpg 300w" sizes="(max-width: 800px) 100vw, 800px" /></a></p>
<p>Exemple de code provoquant un deadlock</p>
<pre class="brush: csharp; title: ; notranslate">

void CreateDeadLock()
{
   Object R1 = new object();
   Object R2 = new object();

   Thread T1 = new Thread(delegate() { Work(R1, R2); });
   Thread T2 = new Thread(delegate() { Work(R2, R1); });

   T1.Start();
   T2.Start();
}

void Work(Object acquire, Object demand)
{
   lock (acquire)//T1 take R1 and T2 take R2
   {
      Thread.Sleep(1000);//To ensure that the ressources are taken
      lock (demand)
      {
      }
    }
}

</pre>
<p>NB : Bien sûr, les situations réelles sont souvent plus compliquées, impliquant par exemple plus de 2 threads ou des locks implicites (écriture dans un fichier…).</p>
<p><span id="more-427"></span></p>
<h2>Le lock C#</h2>
<p>Quand en C# on écrit la syntaxe suivante :</p>
<pre class="brush: csharp; title: ; notranslate">

lock (ressource)
{
}

</pre>
<p>Il se passe en fait à peu près ça :</p>
<pre class="brush: csharp; title: ; notranslate">

Object temp = ressource;
Monitor.Enter(temp);
try
{
}
finally
{
   Monitor.Exit(temp);
}

</pre>
<p>Monitor.Enter acquière le lock, Monitor.Exit le relâche, Le block try-finally est là pour s&#8217;assurer que la ressource sera libérée même en cas d&#8217;exception. Quant à la référence &#8220;temp&#8221;, il garantit que c&#8217;est bien l&#8217;objet acquis qui sera libéré (l&#8217;utilisateur ne peut pas la modifier l&#8217;objet vers lequel &#8220;temp&#8221; pointe).</p>
<h1>Prévenir les deadlocks avec un Timeout</h1>
<p>Le principe pour prévenir les deadlocks implique l’introduction d’un timeout avec un log ou une levée d’exception dans le cas ou le thread échoue à acquérir la ressource demandée.</p>
<p>Voici un exemple de code résolvant le problème.</p>
<pre class="brush: csharp; title: ; notranslate">

if (Monitor.TryEnter(ressource, 10000))
{
   try
   {
      //Work
   }
   finally
   {
      Monitor.Exit();
   }
}
else
{
   // Log, stack trace display...
   throw new TimeoutException(&quot;Lock acquiring failed&quot;);
}

</pre>
<p>Dans une application avec de nombreux locks, vous conviendrez que cette syntaxe est plus lourde et moins lisible que le lock classique.</p>
<p>Plus grave, elle laisse la possibilité « d’oublier » la libération de la ressource puisque celle-ci incombe au programmeur à chaque utilisation (sisi, ça peut arriver !).</p>
<h1>Une solution plus « User-friendly »</h1>
<p>L’objectif est de garder le bénéfice du timeout, tout en bénéficiant d’une syntaxe plus concise et claire.</p>
<p>L’idée ici est d’utiliser un Pattern bien connu des programmeurs C++, mais moins des développeurs C# ou JAVA, le principe RAII (Ressource Acquisition Is Initialization).</p>
<h2>Le principe RAII</h2>
<p>En C++, il y a un moyen simple de s’assurer qu’une ressource sera toujours libérée à la sortie d’une méthode, c’est de l’encapsuler dans un objet créé sur la pile, et de la libérer dans le destructeur de cet objet. En effet, lorsque la méthode se termine (que ce soit par return ou exception), le destructeur de l’objet est appelé et la ressource toujours libérée.</p>
<p>En C# cependant, on ne peut pas appliquer directement cet idiome. En effet :</p>
<p>-L’appel du destructeur d’une classe n’est pas déterministe (il est réalisé par le Garbage Collector)</p>
<p>-Les structures, équivalent C# des objets créé sur la pile en C++, ne peuvent pas avoir de destructeur.</p>
<h2>Implémentation du lock par l’utilisation du pattern IDisposable</h2>
<p>Pour contourner cette limitation du langage, on peut utiliser le pattern IDisposable.</p>
<p>Voici une première implémentation :</p>
<pre class="brush: csharp; title: ; notranslate">

public class LockCookie : IDisposable
{
private const int TIMEOUT = 10000;
private Object _ressource;

public LockCookie(Object ressource)
{
   if (Monitor.TryEnter(ressource, TIMEOUT))
   {
      _ressource = ressource;
   }
   else
   {
      // Log, stack trace display...
      throw new TimeoutException(&quot;Lock acquiring failed&quot;);
   }
}

public void Dispose()
{
   if (_ressource != null)
   {
      Monitor.Exit(_ressource);
   }
}

}

</pre>
<p>Et son utilisation :</p>
<pre class="brush: csharp; title: ; notranslate">

using (new LockCookie(ressource))
{
   //Work
}

</pre>
<p>Avec ce pattern, une seule ligne permet d’acquérir la ressource, la libération est systématique à l’accolade fermante (même en cas d’exception) et le traitement en cas d’échec n’est pas dupliqué.</p>
<p>CQFD ? Pas tout à fait. Même si l’on peut se satisfera de cette solution dans la plupart des cas, elle créé un overhead non négligeable : il y a création d’objet à chaque acquisition de la ressource (et qui dit création d’objet dit également plus de travail pour le Garbage Collector !).</p>
<h2>Optimisation de la solution</h2>
<p>Eliminons tout de suite une première piste : transformer notre classe LockCookie en type struct n’optimise pas la solution. Pourquoi ? Parce qu’à l’accolade fermante du using, la méthode Dispose de l’interface IDisposable est appelée, et appeler une méthode d’interface à partir d’un type struct implique un boxing.</p>
<p>Une autre piste consiste à faire de notre classe LockCookie l’objet même de synchronisation. Voici le code qui en résulte.</p>
<pre class="brush: csharp; title: ; notranslate">

public class LockCookie : IDisposable
{
private const int TIMEOUT = 10000;
private bool _ressourceAcquired;

public LockCookie Get()
{
   _ressourceAcquired = Monitor.TryEnter(this, TIMEOUT);
   if (!_ressourceAcquired)
   {
      throw new TimeoutException(&quot;Lock acquiring failed&quot;);
   }
   return this;
}

public void Dispose()
{
   if (_ressourceAcquired)
   {
      //NB : the 2 next lines must be in is order to prevent _ressourceAcquired
      //to be set to true by Get() then reset by this call to dispose
      _ressourceAcquired = false;
      Monitor.Exit(this);
   }
}

}

</pre>
<p>Et son utilisation :</p>
<pre class="brush: csharp; title: ; notranslate">
//For instance, ressource is a class field : LockCookie _ressource = new LockCookie();
using (_ressource.Get())
{
   //Work
}
</pre>
<p>L’utilisation est sans doute un peu moins évidente, mais aucun objet n’est créé et la libération de la ressource reste implicite et systématique.</p>
<p>Sur le plan des performances, un lock classique coûte selon mes tests 40 ns (40 milliardièmes de secondes), avec la première solution (avec création d’objet), le coût monte à 50 ns, soit un overhead de 25%, la seconde solution descent à 44 ns, soit un overhead de 10%. Le code des tests de performances sont disponibles en bas de l’article.</p>
<h3>Conclusion</h3>
<p>Ces 2 solutions apportent une réponse centralisée et efficace aux problèmes liés aux acquisitions de ressources en général et aux deadlocks en particulier. Le coût en terme de performance peut paraître important à certains, mais gardons à l’esprit que le temps d’acquisition d’un lock est souvent négligeable en comparaison du temps ou un thread est effectivement bloqué en l’attente d’une ressource. Je suis par ailleurs curieux de connaître d’éventuelles améliorations ou corrections que vous pourriez apporter.</p>
<p>Code d&#8217;analyse de la performance :</p>
<p>void TestPerf()<br />
{<br />
   TestPerf(ClassicLock,&#8221;ClassicLock&#8221;);<br />
   TestPerf(LockCookieCreation,&#8221;LockCookieCreation&#8221;);<br />
   TestPerf(LockCookieGet,&#8221;LockCookieGet&#8221;);<br />
}</p>
<p>public static void ClassicLock(){ lock (_lockObject) { }  }<br />
public static void UseLockCookie(){using (new LockCookie(ressource)){ } }<br />
public static void UseLockCookie() { using (ressource.Get()) { } }</p>
<p>public delegate void TestPerfDelegate();<br />
public static void TestPerf(TestPerfDelegate testPerfDelegate, string testName)<br />
{<br />
   const long nbIteration = 10000000;//10 millions times<br />
   const long nanoSecCoeff = 1000000;//1 ms contains 1 million ns</p>
<p>   Stopwatch stopwatch = new Stopwatch();<br />
   GC.Collect();//Prevent from garbage collection during loop<br />
   stopwatch.Start();<br />
   for (int i = 0; i < nbIteration; i++)
   {
      testPerfDelegate();
   }
   stopwatch.Stop();
   double ellapsedNanoSec = (double)(stopwatch.ElapsedMilliseconds * nanoSecCoeff) / nbIteration;
   Console.WriteLine(testName.PadRight(50) + ellapsedNanoSec);
}

}
[/sourcecode]
</p><p>The post <a href="https://blog.infine.com/detecter-les-deadlocks-en-c-net-grace-au-pattern-idisposable-427">Détecter les deadlocks en C# / .NET grâce au pattern IDisposable</a> first appeared on <a href="https://blog.infine.com">In Fine - Le Blog</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://blog.infine.com/detecter-les-deadlocks-en-c-net-grace-au-pattern-idisposable-427/feed</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
