c# - 在 Hololens 上评估 OpenFilePicker 时调用 System.Exception
问题描述
我正在将 MRTK 用于 hololens 应用程序,我需要选择用户放入其文档文件夹中的文件。我正在尝试访问 FileOpenPicker 并通过按下按钮使用 PickSingleFileAsync() 函数来获取文件,然后将其加载到我的应用程序中。
这个函数里面的代码基本上就是我在做的:
private async void PickAFileButton_Click(object sender, RoutedEventArgs e)
{
// Clear previous returned file name, if it exists, between iterations of this scenario
OutputTextBlock.Text = "";
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
// Application now has read/write access to the picked file
OutputTextBlock.Text = "Picked photo: " + file.Name;
}
else
{
OutputTextBlock.Text = "Operation cancelled.";
}
}
但是,当我构建并部署到 Hololens Emulator 时,当我按下按钮时,它会很好地运行代码的第一部分,但在这一行出现异常
StorageFile file = await openPicker.PickSingleFileAsync();
经过广泛的研究和一些挫折后,我在这里发表了一篇非常糟糕和模糊的帖子。
在那篇文章中,我引用了 2 年前发表的这篇文章,并说你不能这样做,但Hololens 的 Microsoft 文档说你可以使用文件选择器,在这种情况下是 FileOpenPicker。
我在 Windows Mixed Reality 开发人员论坛中发现了这篇文章,虽然这不是我遇到的问题,但我仍然觉得有必要将其包含在这篇文章中。
我还想补充一点,我确实安装了一个文件选择器应用程序。根据Microsoft Docs 上的这篇文章,如果您调用 FileOpenPicker,它将打开您设备上首次安装的任何文件选择器。
同样在 MRTK 和正在生成的 Appx 中,我确保启用“PictureLibrary”功能的权限。
任何帮助将不胜感激,我觉得我已经等了太久才能就这个主题发表更正式的帖子,我希望能得到一些答案。谢谢!
解决方案
感谢这篇文章!我终于找到了解决我的问题的方法。在我浏览的任何文档中都没有提到的最大的电话是这个UnityEngine.WSA.Application.InvokeOnUIThread()
我没有遇到这个问题,也没有找到任何文档说明这是 MRTK+unity for hololens 开发的解决方案。因此,对于在那里寻找问题解决方案的任何人,我将引用上面的链接,以防它在未来被破坏。
#if !UNITY_EDITOR && UNITY_WSA_10_0
Debug.Log("***********************************");
Debug.Log("File Picker start.");
Debug.Log("***********************************");
UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
{
var filepicker = new FileOpenPicker();
// filepicker.FileTypeFilter.Add("*");
filepicker.FileTypeFilter.Add(".txt");
var file = await filepicker.PickSingleFileAsync();
UnityEngine.WSA.Application.InvokeOnAppThread(() =>
{
Debug.Log("***********************************");
string name = (file != null) ? file.Name : "No data";
Debug.Log("Name: " + name);
Debug.Log("***********************************");
string path = (file != null) ? file.Path : "No data";
Debug.Log("Path: " + path);
Debug.Log("***********************************");
//This section of code reads through the file (and is covered in the link)
// but if you want to make your own parcing function you can
// ReadTextFile(path);
//StartCoroutine(ReadTextFileCoroutine(path));
}, false);
}, false);
Debug.Log("***********************************");
Debug.Log("File Picker end.");
Debug.Log("***********************************");
#endif
编辑:
关于“InvokeOnUIThread”和“InvokeOnAppThread”含义的一点解释。
想想您的 MRTK 应用程序在 hololens 上运行的方式,您的应用程序在它自己的小环境中运行,并在您的应用程序中使用 MRTK 特定的统一引擎处理函数调用。然后,该应用程序在 hololens 的更大应用程序(操作系统)中运行。因此,每当您调用 UWP 特定函数时,只有 hololens 才能理解的内容,您需要在 InvokeOnUIThread 中调用这些函数。现在,当您在该函数调用中运行时,如果您需要对 MRTK、unity 或您自己创建的函数进行任何函数调用,则需要使用 InvokeOnAppThread。这实质上是告诉应用程序您想要进行一些 UWP 函数调用,然后在任何时候如果您需要从 UWP 函数调用传回任何信息,同时仍在 InvokeOnUIThread 调用中,
据我发现,这基本上就是整个事情的运作方式,我认为这对记录很重要。
推荐阅读
- dataframe - 如何获取火花数据框中每列的空单元格数
- java - 使用 SuperBuilder 使用 Lombok 扩展父类
- java - 使用从未在方法主体中抛出的 throws 子句声明检查的异常
- vue.js - Vue x 模块命名空间
- java - MongoDB Java驱动程序〜“类包含尚未专门化的泛型类型。” - 不包含泛型类型的类错误
- wpf - 如何基于 MaterialDesign 构建自定义组件?
- ios - 为 iOS 11.0 编译,但模块的最低部署目标为 iOS 13.0
- javascript - 如何避免 chrome 扩展在单击其他地方时关闭
- typescript - package.json “abc-domains”:“最新”,不工作
- python-3.x - 如何在 selenium python (Pytest) 中验证禁用的文本框