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

基于Unity的Hololens应用如何后台加载字节数组且不阻塞UI交互

问题根因

  • 直接在UnityEngine.WSA.Application.InvokeOnUIThread回调中同步执行LoadBytes逻辑时,所有IO操作都跑在UI线程,必然阻塞UI导致卡顿
  • 此前Task.Run触发UI冻结的核心原因有两点:
    • UWP的StorageFile属于COM对象,仅允许在创建它的UI线程访问成员(包括Path属性),跨线程访问会触发线程同步甚至异常,间接阻塞UI
    • 非线程安全的List<T>直接跨线程读写,会触发线程竞争,严重时会直接闪退

解决方案

核心逻辑为先在UI线程提取所有待加载文件的路径字符串,再用异步IO在后台加载字节数组,加载完成后切回UI线程更新结果,全程不阻塞UI交互。

代码修改示例

首先修改按钮触发的加载函数:

public void LoadSomething()
{
    UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
    {
        // 加载首批20个字节数组并展示第一张图片
        var firstBatch = manager.listOfStorageFiles.Take(20).ToList();
        foreach (var file in firstBatch)
        {
            var data = File.ReadAllBytes(file.Path);
            manager.byteList.Add(data);
        }
        // 此处补充展示第一张Sprite的业务逻辑
        ShowFirstSprite();

        // UI线程提前提取所有剩余文件的路径,避免跨线程访问StorageFile
        var remainingPaths = manager.listOfStorageFiles.Skip(20)
                                        .Select(f => f.Path)
                                        .ToList();

        // 后台异步加载剩余字节,不阻塞UI
        _ = LoadRemainingBytesAsync(remainingPaths);
    }, false);
}

新增异步加载剩余文件的函数:

private async Task LoadRemainingBytesAsync(List<string> remainingPaths)
{
    await Task.Run(async () =>
    {
        foreach (var path in remainingPaths)
        {
            // 采用异步IO读取文件,进一步降低线程阻塞
            byte[] fileData = await File.ReadAllBytesAsync(path);
            // 切回UI线程更新字节列表,避免线程安全问题
            UnityEngine.WSA.Application.InvokeOnUIThread(() =>
            {
                manager.byteList.Add(fileData);
            }, false);
            // 可选:每加载完成加10ms等待,避免CPU占用过高导致UI掉帧
            await Task.Delay(10);
        }
    });

    // 全部加载完成后的回调逻辑(可选)
    UnityEngine.WSA.Application.InvokeOnUIThread(() =>
    {
        Debug.Log("所有图片字节数组预加载完成");
    }, false);
}

注意事项

  • 若需要更高加载速度,可删除Task.Delay(10)逻辑,Hololens设备CPU最多支持同时并行加载2-3个文件,可自行调整并行度,注意不要超过3个避免IO阻塞。
  • 所有Unity对象的读写操作必须在UI线程执行,字节数组属于普通C#对象,可在后台线程创建,仅更新到MonoBehaviour字段时切回UI线程即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 12:45:03