Good day. Trying to download and put an image in Image.

async public void LoadAvatar() { MainWindow.Instance.AvatarLoadBar.Value += 30; byte[] imgbyte = await GetImgByte(); MainWindow.Instance.AvatarLoadBar.Value += 30; Bitmap avatarbit = await ByteToImage(imgbyte); MainWindow.Instance.AvatarLoadBar.Value += 40; ConvertImage(avatarbit); } async public Task<byte[]> GetImgByte() { WebClient ftpClient = new WebClient(); ftpClient.Credentials = new NetworkCredential("*****", "*****"); byte[] imageByte = await ftpClient.DownloadDataTaskAsync(avatar); return await Task.FromResult(imageByte); } 

where avatar is the image link.

  async public static Task<Bitmap> ByteToImage(byte[] blob) { MemoryStream mStream = new MemoryStream(); byte[] pData = blob; mStream.Write(pData, 0, Convert.ToInt32(pData.Length)); Bitmap bm = new Bitmap(mStream, false); mStream.Dispose(); return await Task.FromResult(bm); } public void ConvertImage(Bitmap bmp) { BitmapSource b = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(bmp.Width, bmp.Height)); MainWindow.Instance.AvatarLoadBar.Visibility =System.Windows.Visibility.Hidden; } 

I made everything possible asynchronous, but I catch the frieze after the first

  MainWindow.Instance.AvatarLoadBar.Value += 30; 

And then the progress bar disappears and the picture appears. I would like to understand why 2 more cannot work.

  MainWindow.Instance.AvatarLoadBar.Value += 30; MainWindow.Instance.AvatarLoadBar.Value += 40; 
  • 1) I assume that due to the fact that conversion operations are performed very quickly. Put await Task.Delay(1500) after the second and third change of the ProgressBar value. 2) I do not understand why to call Task.FromResult if you need to return the result. 3) ByteToImage method synchronous. There is no need to screw Task there. 4) Use using in ByteToImage . - Vlad
  • Thanks to everyone, everything worked - Pavel Anuliev
  • I suggested adding the delay in order to confirm the assumption. It does not need to be left in the finished code. - Vlad

1 answer 1

You have only one asynchronous method, GetImgByte, then everything runs synchronously. Why are you doing Task.FromResult everywhere? The method of this does not become asynchronous, in the first case it is generally superfluous. In ByteToImage, if you want to make it asynchronous, and to return the UI control to the stream to redraw the progress of the bar, you need to make a Task.

 async public Task<byte[]> GetImgByte() { WebClient ftpClient = new WebClient(); ftpClient.Credentials = new NetworkCredential("*****", "*****"); return await ftpClient.DownloadDataTaskAsync(avatar); } async public static Task<Bitmap> ByteToImage(byte[] blob) { return await Task.Run(() => { using(var mStream = new MemoryStream()) { byte[] pData = blob; mStream.Write(pData, 0, Convert.ToInt32(pData.Length)); return new Bitmap(mStream, false); } }); } 
  • 2
    Disagree with the ByteToImage method. It is in itself synchronous. It makes sense to leave him that way so that he can call him in sync. If you want to call it asynchronously, then we wrap it in the place where await Task.Run(() => ByteToImage(bytes) called. - Vlad