You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ListView实现十六进制查看器出现加载卡顿,该如何优化

ListView十六进制查看器性能优化方案

问题根因

你当前代码卡顿的核心原因有两个:

  • ListView默认每次添加条目都会触发重绘,批量添加时会产生大量无用的UI渲染开销
  • 所有文件读取、条目生成逻辑都在UI线程执行,执行过程中UI线程被完全阻塞,导致程序无响应

快速修复方案(小文件适用,改造成本极低)

只需要在添加条目前后增加BeginUpdate和EndUpdate调用,合并所有重绘操作,即可获得10倍以上的性能提升,修改后的核心代码如下:

private void Button_SearchFile_Click(object sender, EventArgs e)
{
    OpenFileDialog_SearchFile.Filter = "SFX Files (*.sfx)|*.sfx";
    DialogResult openEuroSoundFileDlg = OpenFileDialog_SearchFile.ShowDialog();
    if (openEuroSoundFileDlg == DialogResult.OK)
    {
        string filePath = OpenFileDialog_SearchFile.FileName;
        Textbox_FilePath.Text = filePath;
        ListView_HexEditor.Items.Clear();
        // 暂停ListView重绘
        ListView_HexEditor.BeginUpdate();
        using (BinaryReader BReader = new BinaryReader(File.OpenRead(filePath)))
        {
            byte[] bytesRow = new byte[16];
            while (BReader.BaseStream.Position != BReader.BaseStream.Length)
            {
                long offset = BReader.BaseStream.Position;
                byte[] readedBytes = BReader.ReadBytes(16);
                Buffer.BlockCopy(readedBytes, 0, bytesRow, 0, readedBytes.Length);
                ListView_HexEditor.Items.Add(new ListViewItem(new[]
                {
                    offset.ToString("X8"),
                    ((bytesRow[0] << 8) | bytesRow[1]).ToString("X4"),
                    ((bytesRow[2] << 8) | bytesRow[3]).ToString("X4"),
                    ((bytesRow[4] << 8) | bytesRow[5]).ToString("X4"),
                    ((bytesRow[6] << 8) | bytesRow[7]).ToString("X4"),
                    ((bytesRow[8] << 8) | bytesRow[9]).ToString("X4"),
                    ((bytesRow[10] << 8) | bytesRow[11]).ToString("X4"),
                    ((bytesRow[12] << 8) | bytesRow[13]).ToString("X4"),
                    ((bytesRow[14] << 8) | bytesRow[15]).ToString("X4"),
                    GetHexStringFormat(bytesRow)
                }));
            }
        }
        // 恢复重绘,一次性渲染所有条目
        ListView_HexEditor.EndUpdate();
    }
}

private string GetHexStringFormat(byte[] inputBytes)
{
    char[] arrayChars = Encoding.ASCII.GetChars(inputBytes);
    for (int i = 0; i < inputBytes.Length; i++)
    {
        if (char.IsControl(arrayChars[i]) || (arrayChars[i] == '?' && inputBytes[i] != 63))
        {
            arrayChars[i] = '.';
        }
    }
    return new string(arrayChars);
}

终极优化方案(大文件适用,无卡顿)

如果需要打开几十MB以上的大文件,推荐使用ListView的虚拟模式,核心逻辑是:只渲染当前可视区域的条目(你的控件高度固定795px,可视区域最多30行左右),不需要提前加载所有条目,滚动时动态生成对应行的内容即可,完全避免卡顿,实现步骤如下:

  1. 在设计器中将ListView_HexEditor的VirtualMode属性设置为True
  2. 全局定义存储文件内容的字节数组:private byte[] _fileBytes;
  3. 文件读取完成后设置虚拟列表总长度:ListView_HexEditor.VirtualListSize = (int)Math.Ceiling(_fileBytes.Length / 16.0);
  4. 订阅RetrieveVirtualItem事件,动态生成对应行的内容:
private void ListView_HexEditor_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
    int startOffset = e.ItemIndex * 16;
    int length = Math.Min(16, _fileBytes.Length - startOffset);
    byte[] bytesRow = new byte[16];
    Buffer.BlockCopy(_fileBytes, startOffset, bytesRow, 0, length);
    e.Item = new ListViewItem(new[]
    {
        startOffset.ToString("X8"),
        ((bytesRow[0] << 8) | bytesRow[1]).ToString("X4"),
        ((bytesRow[2] << 8) | bytesRow[3]).ToString("X4"),
        ((bytesRow[4] << 8) | bytesRow[5]).ToString("X4"),
        ((bytesRow[6] << 8) | bytesRow[7]).ToString("X4"),
        ((bytesRow[8] << 8) | bytesRow[9]).ToString("X4"),
        ((bytesRow[10] << 8) | bytesRow[11]).ToString("X4"),
        ((bytesRow[12] << 8) | bytesRow[13]).ToString("X4"),
        ((bytesRow[14] << 8) | bytesRow[15]).ToString("X4"),
        GetHexStringFormat(bytesRow)
    });
}

程序运行效果

程序运行界面

内容的提问来源于stack exchange,提问作者jms2505

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 06:15:04