I'm trying to make a simple winforms app to convert an image to Base64. When debugging I notice that the ui freezes when I click the button to convert to base64, so I started making changes in the code to call the method asynchronously. (It happens that I never used Async methods so I kinda don't know what I'm doing)
My form1.cs code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ImageToBase64
{
public partial class main : Form
{
public main()
{
InitializeComponent();
}
Util Util = new Util();
private void button1_Click(object sender, EventArgs e)
{
imageDialog.FileName = "";
imageDialog.Title = "Selecionar Imagem";
imageDialog.Filter = "JPEG|*.JPG|PNG|*.png";
imageDialog.ShowDialog();
imagePathText.Text = imageDialog.FileName;
}
private void button2_Click(object sender, EventArgs e)
{
imageCode.Text = "";
Task<string> base64Code = Task.Run(() => Util.ToBase64(imageDialog.FileName));
imageCode.Text = base64Code.Result;
}
}
}
My Util.cs code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ImageToBase64
{
class Util
{
public async Task<string> ToBase64(string img)
{
string path = img;
using (System.Drawing.Image image = System.Drawing.Image.FromFile(path))
{
using (MemoryStream m = new MemoryStream())
{
image.Save(m, image.RawFormat);
byte[] imageBytes = m.ToArray();
string base64String = null;
base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}
}
}
}
Even after these changes the UI still freezes, what can I do to fix that?
CodePudding user response:
First, the code blocks the task. Second, the method ToBase64
ends up producing and encoding the original bytes, assuming nothing is lost due to lossy compression. image.Save(m, image.RawFormat);
saves the image data in the original format, so at best it produces the same data.
The code could be reduced to:
private async void button2_Click(object sender, EventArgs e)
{
//Only needed to provide a visual cue
imageCode.Text="";
var bytes=await File.ReadAllBytes(imageDialog.FileName);
imageCode.Text = await Task.Run(()=>Convert.ToBase64String(bytes));
}
Using an Image
would make sense if you wanted to convert the image to a different format before encoding, or if you wanted to encode the raw RGB values
CodePudding user response:
The reason is this
imageCode.Text = base64Code.Result;
.Result
will block until the string can be produced, and that is probably not what you want.
You should instead be using async/await:
imageCode.Text = await base64Code;
Note that this requires the method to be marked as async. And you probably also want to catch any exceptions, since they otherwise risk being lost.
I would also recommend using some profiling tools, since these can usually tell you what parts of the code is blocking the UI.