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

如何在Unity中等待HoloLens 2的UWP文件选择器关闭?

HoloLens 2 Unity开发:UWP与Unity线程交互下等待FileOpenPicker完成的解决方案

我正在用Unity开发HoloLens 2应用,需要搞懂UWP环境和.NET/Unity环境的交互切换方法。现在遇到的问题是,点击按钮调用FileOpenPicker.PickSingleFileAsync()获取文件路径时,FilePicker_Hololens()方法在文件对话框还没关闭就返回了已完成的Task,导致调用StartPicker()的代码同步执行,没等到选择结果就继续走了。我猜问题出在UnityEngine.WSA.Application.InvokeOnUIThread和InvokeOnAppThread的跨线程委托调用上,请问该怎么实现等待对话框关闭后再继续执行?


代码示例

Part1:调用选择器的入口方法
调用方会通过await执行StartPicker()来获取文件名,用于后续计算

public async Task<String> StartPicker()
{
    #if !UNITY_EDITOR && UNITY_WSA_10_0
    Debug.Log("HOLOLENS 2 PICKER");
    await FilePicker_Hololens();
    #endif

    #if UNITY_EDITOR
    Debug.Log("UNITY_STANDALONE PICKER");
    await FilePicker_Win();
    #endif

    // 当前这里返回空字符串,因为调用的任务提前完成了
    return filePath;
}

Part2:HoloLens平台的文件选择实现
负责调用UWP的文件选择器,LoadDataset()是实际加载数据的方法,也需要等待选择完成后执行

#if !UNITY_EDITOR && UNITY_WSA_10_0
private async Task FilePicker_Hololens()
{
    // UWP的文件选择器必须在UI线程执行
    UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
        {
            var filepicker = new FileOpenPicker();
            filepicker.FileTypeFilter.Add("*");
            filepicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;

            var file = await filepicker.PickSingleFileAsync();

            // 文件选择器关闭后切回Unity的App线程处理结果
            UnityEngine.WSA.Application.InvokeOnAppThread(async () =>
            {
                filePath = (file != null) ? file.Path : "Nothing selected";
                await LoadDataset();
            }, true);
        }, true);
    // 当前这里直接返回了完成态的Task,没有等待对话框操作完成
}
#endif

解决方案

核心问题是InvokeOnUIThread仅异步触发委托,但不会返回可等待的Task,导致外层的FilePicker_Hololens()提前结束。我们可以用TaskCompletionSource手动控制Task的完成时机,实现等待对话框关闭及后续操作完成。

修改后的FilePicker_Hololens()代码如下:

#if !UNITY_EDITOR && UNITY_WSA_10_0
private async Task FilePicker_Hololens()
{
    // 创建TaskCompletionSource来跟踪对话框及后续操作的完成状态
    var tcs = new TaskCompletionSource<bool>();

    UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
        {
            var filepicker = new FileOpenPicker();
            filepicker.FileTypeFilter.Add("*");
            filepicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;

            var file = await filepicker.PickSingleFileAsync();
            var selectedPath = (file != null) ? file.Path : "Nothing selected";
            
            // 切回Unity App线程处理结果和加载逻辑
            UnityEngine.WSA.Application.InvokeOnAppThread(async () =>
            {
                filePath = selectedPath;
                await LoadDataset();
                // 手动标记任务完成,让外层await继续执行
                tcs.SetResult(true);
            }, true);
        }, true);

    // 等待直到对话框操作和数据加载都完成
    await tcs.Task;
}
#endif

关键修改点说明

  • 用TaskCompletionSource<bool>创建一个可手动控制的Task,外层方法通过await tcs.Task等待,直到我们主动调用SetResult
  • 在App线程完成LoadDataset()后再调用tcs.SetResult(true),确保所有后续逻辑执行完毕后,外层的await FilePicker_Hololens()才会继续
  • 将文件路径赋值和LoadDataset()放在同一个App线程委托中,避免跨线程数据同步问题

额外注意事项

  • 确保filePath仅在Unity App线程中访问和修改,避免多线程竞争
  • 如果LoadDataset()是耗时操作,保持其异步执行,不要阻塞线程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 16:10:33