将图像异步转换为 Base64 的 C# 简单应用程序

Posted

技术标签:

【中文标题】将图像异步转换为 Base64 的 C# 简单应用程序【英文标题】:C# Simple app to convert images into Base64 asynchronously 【发布时间】:2022-01-19 09:24:53 【问题描述】:

我正在尝试制作一个简单的 winforms 应用程序来将图像转换为 Base64。调试时,我注意到当我单击转换为 base64 的按钮时 ui 冻结,因此我开始更改代码以异步调用该方法。 (碰巧我从来没有使用过 Async 方法,所以我有点不知道自己在做什么)

我的 form1.cs 代码:

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;
            
        
    

我的 Util.cs 代码:

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;
                
            
        
    

即使在进行了这些更改后,UI 仍然冻结,我可以做些什么来解决这个问题?

【问题讨论】:

base64Code.Result; - 您正在以同步的方式访问任务的结果,阻止一切。你必须让你的button2_Click异步。 请改用await Task.Run(() =&gt; Util.ToBase64(...)。这个方法也很可疑——为什么要使用Image?这将编码原始 RGB 字节而不是文件数据。您可以使用var imageBytes=await File.ReadAllBytesAsync(path); var base64=Convert.ToBase64String(imageBytes); 转换文件数据 ToBase64 没有做任何有用的事情 - 除了由于有损压缩而降低质量之外,它产生的字节与存储在文件中的字节相同。 【参考方案1】:

首先,代码阻塞了任务。其次,方法ToBase64 最终生成和编码原始 字节,假设没有由于有损压缩而丢失。 image.Save(m, image.RawFormat); 以原始格式保存图像数据,因此最多只能生成相同的数据。

代码可以简化为:

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));

如果您想在编码之前将图像转换为不同的格式,或者如果您想对原始 RGB 值进行编码,则使用 Image 会很有意义

【讨论】:

【参考方案2】:

原因是这样的

imageCode.Text = base64Code.Result;

.Result 将阻塞直到可以生成字符串,这可能不是您想要的。

您应该改用 async/await:

imageCode.Text = await base64Code;

请注意,这需要将方法标记为异步。而且您可能还想捕获任何异常,否则它们可能会丢失。

我还建议使用一些分析工具,因为这些工具通常可以告诉您代码的哪些部分阻塞了 UI。

【讨论】:

以上是关于将图像异步转换为 Base64 的 C# 简单应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# 将数据库中的 base64 值转换为流

我想将图像数据(Texture2D)转换为 Base64 字符串并存储在 Unity3D(C#)中的 JSON 文件中

将图像(按路径选择)转换为 base64 字符串

C# Base64 字符串到 JPEG 图像

在 iOS 上使用 Phonegap 将图像转换为 Base64 字符串

如何从 C++ 中的 Base64 编码字符串在 GDI+ 中创建图像?