【问题标题】:async Task.Run lambda expression crashes Unity AR app on android but works fine on iOSasync Task.Run lambda 表达式在 Android 上使 Unity AR 应用程序崩溃,但在 iOS 上运行良好
【发布时间】:2021-09-23 23:34:16
【问题描述】:

我正在使用 Unity 2020.3.4 和 ARCore 4.0.12 以及 Azure Spatial Anchors 2.8.1 创建一个应用程序。它是适用于 Android 和 iOS 的跨平台应用程序。首先,我创建了一个 iOS 版本,在其中创建了一个 Task.Run(async() =>{ }); void 函数中的 lambda 表达式,以便能够调用 Azure 空间锚的异步函数。我是这样做的,因为这个函数是在按下 Unity 按钮时调用的,它不需要异步任务,但它确实需要 void。这在 iOS 设备上运行良好,但在我在 Android 设备上测试后,此代码使应用程序崩溃。

//Called on Unity UI button press, works fine on IOS, but crashes the app on Android
public void BROKENStartLookingForAnchor()
{
    Task.Run(async () =>
    {
        if (!hasStartedOnce)
        {
            await StorageManager.instance.InitializeStorage();
            anchorId = await StorageManager.instance.DownloadBlob(blobName);
        }

        spatialAnchorManager.SessionStarted += OnSessionStarted;
        spatialAnchorManager.AnchorLocated += CloudManager_AnchorLocated;

        anchorLocateCriteria = new AnchorLocateCriteria();

        if (spatialAnchorManager.Session == null)
        {
            await spatialAnchorManager.CreateSessionAsync();
            SetAnchorLocateCriteria();
        }

        await spatialAnchorManager.StartSessionAsync();
    });
}

一开始很难找出问题所在(我使用 LogCat 进行调试),但是一旦我将代码更改为以下代码,它在 Android 上也能正常工作。

//Called on Unity UI button press, because cannot call async Task from Unity button press
public async void StartLookingForAnchor()
{
    await StartLookingForAnchorAsync();
}

private async Task StartLookingForAnchorAsync()
{
    if (!hasStartedOnce)
    {
        await StorageManager.instance.InitializeStorage();
        anchorId = await StorageManager.instance.DownloadBlob(blobName);
    }

    spatialAnchorManager.SessionStarted += OnSessionStarted;
    spatialAnchorManager.AnchorLocated += CloudManager_AnchorLocated;

    anchorLocateCriteria = new AnchorLocateCriteria();

    if (spatialAnchorManager.Session == null)
    {
        await spatialAnchorManager.CreateSessionAsync();
        SetAnchorLocateCriteria();
    }

    await spatialAnchorManager.StartSessionAsync();
}

但是,即使我解决了这个问题,我仍然不确定为什么第一个选项在 Android 上不起作用,以及为什么第二个可以,因为我对异步函数和多线程不是很熟悉。谁能给我解释一下?

【问题讨论】:

    标签: c# android ios unity3d


    【解决方案1】:

    查看这些问题

    https://github.com/Azure/azure-spatial-anchors-samples/issues/230 https://github.com/Azure/azure-spatial-anchors-samples/issues/283

    如果您遇到类似错误,请尝试 Vastja 提到的解决方法

    【讨论】:

      【解决方案2】:

      Task.Run(async () => { ... }); 返回一个Task,在您的第一个版本中没有等待,其中BROKENStartLookingForAnchorAsync() 的返回类型仅为void

      在您的第二个版本中,等待由async Task StartLookingForAnchorAsync() 返回的Task(这可以通过具有async void 返回类型的StartLookingForAnchor() 实现)。

      我怀疑如果您将第一个版本返回 async void 并将代码设置为 await Task.Run(async () => { ... });,或者只是删除了完全包裹其余代码的 Task.Run(),那么您的第一个版本也可以工作。

      不鼓励使用 C# async documentationasync void 返回类型,但事件处理程序除外,这听起来像是按下 Unity 按钮的用例。

      Unity QuickStart tutorials in the Azure Spatial Anchors documentation 可能是用于 Unity + ASA 的模式的良好起点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-31
        • 1970-01-01
        • 2017-12-05
        相关资源
        最近更新 更多