Remember UWP Development--multi-threaded operations/pits in concurrent operations

Source: Internet
Author: User

Everything has to start with the new version of the windmill anime UWP picture cache feature.

The cause is the Windmill Animation official website of the play update is very slow, so the picture update is very slow. In the development of the new version of the process, I was very simple to think of the picture repeated download caused by the resource waste problem.

So I added a caching mechanism to the app:

Create a user control Coverview, change the image in the first page gridview.itemtemplate to Coverview

Coverview once received ImageUrl changes, will automatically apply to the background of the picturehelper to specify the URL of the picture

Picturehelper will first determine if there is a local image of this URL, no words from the Windmill animation website Download a copy, save to local, and then return to Coverview

The key is the Getimageasync method of Picturehelper

Code snippet for locally cached picture:

    //cached file names are saved as MD5 in the local    stringName =stringhelper.md5encrypt16 (URL); if(Imagefolder = =NULL) Imagefolder=awaitCachefolder.createfolderasync ("Imagecache", creationcollisionoption.openifexists);    StorageFile file; Irandomaccessstream Stream=NULL; if(File.exists (Imagefolder.path +"\\"+name)) {File=awaitImagefolder.getfileasync (name); Stream=awaitfile.    OpenReadAsync (); }    //file does not exist or file is empty, download via HTTP    if(Stream = =NULL|| Stream. Size = =0) {file=awaitImagefolder.createfileasync (name, creationcollisionoption.replaceexisting); Stream=awaitfile.        OpenAsync (Fileaccessmode.readwrite); IBuffer Buffer=awaitHttphelper.getbufferasync (URL); awaitStream.    WriteAsync (buffer); }        //...

Well... Everything seems to be beautiful ....

But after running, a very serious accidental exception was found.

After looking at Google for a long while, I learned about the cause of the problem:

Home GridView after loading dozens of item at a time, the Coverview in dozens of item calls the Getimageasync method of Picturehelper.

The dozens of Picturehelper Getimageasync method also accesses the cache folder at the same time, causing a very serious IO deadlock problem, which in turn leads to a lot of unauthorizedaccessexception

have = and look after a long time, finally found a solution:

Semaphoreslim Asynchronous lock

Here's how to use it:

        Private StaticSemaphoreslim Asynclock =NewSemaphoreslim (1);//1: Signal capacity, which is up to a few asynchronous threads, set to 1 for the sake of conservatism         Public Async StaticTask<writeablebitmap> Getimageasync (stringUrl) {            if(Url = =NULL)                return NULL; Try            {                awaitAsynclock.waitasync (); //cached file names are saved as MD5 in the local                stringName =stringhelper.md5encrypt16 (URL); if(Imagefolder = =NULL) Imagefolder=awaitCachefolder.createfolderasync ("Imagecache", creationcollisionoption.openifexists);                StorageFile file; Irandomaccessstream Stream=NULL; if(File.exists (Imagefolder.path +"\\"+name)) {File=awaitImagefolder.getfileasync (name); Stream=awaitfile.                OpenReadAsync (); }                //file does not exist or file is empty, download via HTTP                if(Stream = =NULL|| Stream. Size = =0) {file=awaitImagefolder.createfileasync (name, creationcollisionoption.replaceexisting); Stream=awaitfile.                    OpenAsync (Fileaccessmode.readwrite); IBuffer Buffer=awaitHttphelper.getbufferasync (URL); awaitStream.                WriteAsync (buffer); }                //...            }            Catch(Exception error) {Debug.WriteLine ("Cache Image error:"+error.                Message); return NULL; }            finally{asynclock.release (); }        }    

Successfully solved the problem of concurrent access IO

But in the course of the next stream turning writeablebitmap, the problem came again ....

This problem is better solved.

Bitmapdecoder Bitmapdecoder =awaitBitmapdecoder.createasync (stream); WriteableBitmap Bitmap=NULL; awaitWindow.Current.Dispatcher.RunAsync (Windows.UI.Core.CoreDispatcherPriority.Normal,Async Delegate{bitmap=NewWriteableBitmap ((int) Bitmapdecoder.pixelwidth, (int) bitmapdecoder.pixelheight); Stream. Seek (0); awaitbitmap.                Setsourceasync (stream);                }); Stream.                Dispose (); returnBitmap

Use the UI thread to run is OK

And then! Here comes the question again.

WriteableBitmap is normal until it's return.

But then, when I was doing some other bitmap in Coverview, there was this problem.

And looking for a long time, finally back to bitmap pixelbuffer a look, wipe, all empty?

Although bitmap successful new out, pixelheight/width everything has, then the UI thread Setsourceasync not finished, so there is a memory protection of the magic problem

Did you await me?

Finally, using such a artifice, the final successful completion

Bitmapdecoder Bitmapdecoder =awaitBitmapdecoder.createasync (stream); WriteableBitmap Bitmap=NULL; TaskCompletionSource<BOOL> task =Newtaskcompletionsource<BOOL>(); awaitWindow.Current.Dispatcher.RunAsync (Windows.UI.Core.CoreDispatcherPriority.Normal,Async Delegate{bitmap=NewWriteableBitmap ((int) Bitmapdecoder.pixelwidth, (int) bitmapdecoder.pixelheight); Stream. Seek (0); awaitbitmap.                    Setsourceasync (stream); Task. Setresult (true);                }); awaitTask. Task;

For TaskCompletionSource, see

Https://www.cnblogs.com/loyieking/p/9209476.html

Finally it was finished ....

         Public Async StaticTask<writeablebitmap> Getimageasync (stringUrl) {            if(Url = =NULL)                return NULL; Try            {                awaitAsynclock.waitasync (); //cached file names are saved as MD5 in the local                stringName =stringhelper.md5encrypt16 (URL); if(Imagefolder = =NULL) Imagefolder=awaitCachefolder.createfolderasync ("Imagecache", creationcollisionoption.openifexists);                StorageFile file; Irandomaccessstream Stream=NULL; if(File.exists (Imagefolder.path +"\\"+name)) {File=awaitImagefolder.getfileasync (name); Stream=awaitfile.                OpenReadAsync (); }                //file does not exist or file is empty, download via HTTP                if(Stream = =NULL|| Stream. Size = =0) {file=awaitImagefolder.createfileasync (name, creationcollisionoption.replaceexisting); Stream=awaitfile.                    OpenAsync (Fileaccessmode.readwrite); IBuffer Buffer=awaitHttphelper.getbufferasync (URL); awaitStream.                WriteAsync (buffer); } bitmapdecoder Bitmapdecoder=awaitBitmapdecoder.createasync (stream); WriteableBitmap Bitmap=NULL; TaskCompletionSource<BOOL> task =Newtaskcompletionsource<BOOL>(); awaitWindow.Current.Dispatcher.RunAsync (Windows.UI.Core.CoreDispatcherPriority.Normal,Async Delegate{bitmap=NewWriteableBitmap ((int) Bitmapdecoder.pixelwidth, (int) bitmapdecoder.pixelheight); Stream. Seek (0); awaitbitmap.                    Setsourceasync (stream); Task. Setresult (true);                }); awaittask.                Task; Stream.                Dispose (); returnbitmap; }            Catch(Exception error) {Debug.WriteLine ("Cache Image error:"+error.                Message); return NULL; }            finally{asynclock.release (); }        }

Remember UWP Development--multi-threaded operations/pits in concurrent operations

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.