{"id":782,"date":"2014-11-24T00:55:35","date_gmt":"2014-11-23T22:55:35","guid":{"rendered":"http:\/\/dev.bratched.fr\/fr\/?p=782"},"modified":"2014-11-24T00:55:35","modified_gmt":"2014-11-23T22:55:35","slug":"mise-en-cache-dimage-dans-lisolated-storage-avec-windows-xaml","status":"publish","type":"post","link":"https:\/\/bratched.com\/fr\/2014\/11\/24\/mise-en-cache-dimage-dans-lisolated-storage-avec-windows-xaml\/","title":{"rendered":"Mise en cache d&rsquo;image dans l&rsquo;isolated storage avec Windows XAML et SemaphoreSlim"},"content":{"rendered":"<p>&nbsp;<\/p>\n<h1>Ecriture dans l&rsquo;isolated Storage d&rsquo;un fichier image<\/h1>\n<p><a href=\"http:\/\/dev.bratched.fr\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/IsolatedStorage.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-783\" src=\"http:\/\/dev.bratched.fr\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/IsolatedStorage.png\" alt=\"Ecriture Multiple dans l'Isolated Storage\" width=\"480\" height=\"360\" srcset=\"https:\/\/bratched.com\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/IsolatedStorage.png 800w, https:\/\/bratched.com\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/IsolatedStorage-300x225.png 300w, https:\/\/bratched.com\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/IsolatedStorage-768x576.png 768w\" sizes=\"(max-width: 480px) 100vw, 480px\" \/><\/a><\/p>\n<p>Il est parfois fort utile de sauvegarder les images provenant d&rsquo;un serveur HTTP dans un cache afin d&rsquo;\u00e9viter de les charger \u00e0 chaque fois.<\/p>\n<p>En impl\u00e9mentant\u00a0ce syst\u00e8me de cache en asynchrone, je me suis rendu compte de plusieurs probl\u00e8mes causant syst\u00e9matiquement un UnauthorizedAccessException: Access is denied (0x80070005).<\/p>\n<p><!--more--><\/p>\n<figure id=\"attachment_784\" aria-describedby=\"caption-attachment-784\" style=\"width: 860px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/dev.bratched.fr\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/ExceptionAccessDenied.png\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-784\" src=\"http:\/\/dev.bratched.fr\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/ExceptionAccessDenied.png\" alt=\"ScreenShot Exception Access Denied\" width=\"860\" height=\"310\" srcset=\"https:\/\/bratched.com\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/ExceptionAccessDenied.png 1113w, https:\/\/bratched.com\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/ExceptionAccessDenied-300x108.png 300w, https:\/\/bratched.com\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/ExceptionAccessDenied-768x277.png 768w, https:\/\/bratched.com\/fr\/wp-content\/uploads\/sites\/2\/2014\/11\/ExceptionAccessDenied-1024x369.png 1024w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><figcaption id=\"caption-attachment-784\" class=\"wp-caption-text\">UnauthorizedAccessException: Access is denied (0x80070005).<\/figcaption><\/figure>\n<p>Le probl\u00e8me rencontr\u00e9 intervient lorsque plusieurs images d&rsquo;une liste essaient d&rsquo;enregistrer des \u00e9l\u00e9ments dans l&rsquo;Isolated Storage en m\u00eame temps.<\/p>\n<p>Pourtant le code me paraissait plut\u00f4t correct ?<\/p>\n<pre class=\"lang:default decode:true \">public async Task&lt;string&gt; SaveImageInStorageAsyncBad(string urlImage, object datas)\n{\n    if (!String.IsNullOrEmpty(urlImage) &amp;&amp; datas is byte[])\n    {\n        string id = urlImage;\n       \n            var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;\n            var folder = await localFolder.CreateFolderAsync(\"DataCache\", Windows.Storage.CreationCollisionOption.OpenIfExists);\n            var file = await folder.CreateFileAsync(id, Windows.Storage.CreationCollisionOption.ReplaceExisting);\n            var stream = await file.OpenStreamForWriteAsync();\n            using (var outStream = stream)\n            {\n                var dataWriter = new Windows.Storage.Streams.DataWriter(outStream.AsOutputStream());\n                dataWriter.WriteBytes(datas as byte[]);\n                await dataWriter.StoreAsync();\n                return id;\n            }\n        \n    }\n    else\n        return String.Empty;\n}\n<\/pre>\n<h1>\u00a0FlushAsync()<\/h1>\n<p>La premi\u00e8re chose qu&rsquo;il manque est un await dataWriter.FlushAsync() juste apr\u00e8s le StoreAsync().<\/p>\n<p>En effet, nous utilisons un Stream pour \u00e9crire l&rsquo;image.<\/p>\n<p>Le Flush permet de s&rsquo;assurer que tout le stream va \u00eatre \u00e9crit correctement avant de continuer.<\/p>\n<h1>Verrou &#8211; Lock ?<\/h1>\n<p>Mais le Flush ne suffit pas l&rsquo;erreur est encore rencontr\u00e9e. Il va falloir prot\u00e9ger le code en \u00e9vitant une \u00e9criture parall\u00e8le des images.<\/p>\n<p>En mode Synchrone un Lock aurait p\u00fb \u00eatre utilis\u00e9 mais nous somme dans un traitement asynchrone.<\/p>\n<p>L&rsquo;utilisation du Lock est interdite car emp\u00eache le thread de continuer. Le compilateur l&rsquo;indique clairement.<\/p>\n<p>Pour assurer une \u00e9criture \u00e0 la fois, nous allons utiliser l&rsquo;objet SemaphoreSlim.<\/p>\n<p>Il faut initialiser\u00a0cet objet de la fa\u00e7on suivante :<\/p>\n<pre class=\"lang:default decode:true\">private SemaphoreSlim _syncLock = new SemaphoreSlim(1);<\/pre>\n<p>Le 1\u00a0en param\u00e8tre indique que nous ne souhaitons q&rsquo;un seul acc\u00e8s concurent.<\/p>\n<p>Pour blocker les acc\u00e8s concurent on appelle la m\u00e9thode :<\/p>\n<pre class=\"lang:default decode:true \">await _syncLock.WaitAsync();<\/pre>\n<p>Pour rendre le block<\/p>\n<pre class=\"lang:default decode:true\">_syncLock.Release();<\/pre>\n<p>&nbsp;<\/p>\n<p>Le code final qui fonctionne sans erreur ressemble maintenant \u00e0 ceci :<\/p>\n<p>A noter\u00a0 : l&rsquo;utilisation du try &#8230; finally pour assurer le d\u00e9verrouillage m\u00eame en cas d&rsquo;anomalies.<\/p>\n<pre class=\"lang:default decode:true \">public async Task&lt;string&gt; SaveImageInStorageAsync(string urlImage, object datas)\n{\n    if (!String.IsNullOrEmpty(urlImage) &amp;&amp; datas is byte[])\n    {\n        string id = GetIdStorage(urlImage, savedName);\n        await _syncLock.WaitAsync();\n        try\n        {\n            var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;\n            var folder = await localFolder.CreateFolderAsync(\"DataCache\", Windows.Storage.CreationCollisionOption.OpenIfExists);\n            var file = await folder.CreateFileAsync(id, Windows.Storage.CreationCollisionOption.ReplaceExisting);\n            var stream = await file.OpenStreamForWriteAsync();\n            using (var outStream = stream)\n            {\n                var dataWriter = new Windows.Storage.Streams.DataWriter(outStream.AsOutputStream());\n                dataWriter.WriteBytes(datas as byte[]);\n                await dataWriter.StoreAsync();\n                await dataWriter.FlushAsync();\n                outStream.Dispose();\n                return id;\n            }\n        }\n        finally\n        {\n            _syncLock.Release();\n        }\n    }\n    else\n        return String.Empty;\n}\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Voici donc un m\u00e9canisme fort utile pour am\u00e9liorer la r\u00e9activit\u00e9 de vos applications Windows et Windows Phone<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Ecriture dans l&rsquo;isolated Storage d&rsquo;un fichier image Il est parfois fort utile de sauvegarder les images provenant d&rsquo;un serveur HTTP dans un cache afin d&rsquo;\u00e9viter de les charger \u00e0 chaque fois. En impl\u00e9mentant\u00a0ce syst\u00e8me de cache en asynchrone, je me suis rendu compte de plusieurs probl\u00e8mes causant syst\u00e9matiquement un UnauthorizedAccessException: Access is denied (0x80070005).<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[59,62,63],"tags":[68,69,70,132,133,134,58,8],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts\/782"}],"collection":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/comments?post=782"}],"version-history":[{"count":0,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/posts\/782\/revisions"}],"wp:attachment":[{"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/media?parent=782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/categories?post=782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bratched.com\/fr\/wp-json\/wp\/v2\/tags?post=782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}