For the complete documentation index, see llms.txt. This page is also available as Markdown.

异步模式

使用 async/await、协程、链式调用、进度跟踪、取消和流来消费 IConvaiOperation<T> 和 IConvaiStream<T>。

IConvaiOperation<T>IConvaiStream<T> 支持多种消费模式,因此你可以使用最适合你的代码库的风格——纯异步/await、Unity 协程,或两者混用。有关类型定义和成员引用,请参见 操作与流类型.


异步/await

最直接的模式。可用于任何 async 方法。失败的操作会抛出 ConvaiOperationException.

using Convai.Runtime.Core.Async;
using Convai.Runtime.Facades;
using System.Threading;
using UnityEngine;

public class AsyncConnectExample : MonoBehaviour
{
    private async void Start()
    {
        var manager = ConvaiManager.ActiveManager;
        if (manager == null) return;

        try
        {
            var session = await manager.ConnectAsync(destroyCancellationToken);
            Debug.Log($"已连接。房间:{session.RoomId}");
        }
        catch (ConvaiOperationException ex)
        {
            Debug.LogError($"[{ex.Code}] 连接失败:{ex.Message}");
        }
        catch (OperationCanceledException)
        {
            Debug.Log("连接已取消——场景已卸载。");
        }
    }
}

await operationawait operation.AsTask()

两者结果相同。优先使用 await operation 直接方式——它使用 GetAwaiter() 并避免额外分配。仅在你需要将该操作传递给需要 AsTask() 的某个方法时才使用, Task<T>例如 Task.WhenAll.


协程

当你的脚本无法使用 async (例如,在不支持 async 的 Unity 事件回调中),或者你更喜欢基于回调的流程时,请使用协程。

ToCoroutine 会一直等待直到操作完成。两者 onSuccessonError 都是可选的——如果你不需要回调,就传入 null 用于任一回调。


ContinueWith 链式调用

在不嵌套 await 调用的情况下,将一个操作的结果转换为另一个操作。

ContinueWith 会传播错误:如果源操作失败,链式操作也会以相同错误失败,并且不会调用选择器。


进度跟踪

轮询 operation.Progress 以驱动 UI 进度指示器。该值会从 0.01.0 随着操作完成而推进。并非所有操作都会报告细粒度进度——请检查 Status 以确认最终完成。


取消

使用 CancellationToken

传入一个 CancellationToken 给任意 SDK 方法。操作会转变为 已取消 当令牌被触发时。

使用 destroyCancellationToken

MonoBehaviour.destroyCancellationToken 是针对组件生命周期范围内操作的最简单取消模式——当组件被销毁时,令牌会自动被触发。

使用 operation.Cancel()

调用 Cancel() 直接在操作句柄上进行手动取消,与 CancellationToken.

CancellationTokenoperation.Cancel()

CancellationToken

operation.Cancel()

来源

外部(CancellationTokenSource)

操作句柄

使用场景

组件生命周期、超时、联动取消

通过按钮或事件取消单个操作

兼容协程

在操作创建时传入

可随时在句柄上调用


使用 IConvaiStream<T>await foreachawait using 用于资源清理。

ReadAllAsync 返回 IAsyncEnumerable<T>。当流到达 已完成, 失败,或 已取消时循环退出。务必包裹在 await using 以便 调用 DisposeAsync() 即使循环提前退出也会执行。


错误处理决策表

场景
模式
原因

async void MonoBehaviour 方法

使用 try/catch 的异步/await

天然契合;故障会以异常形式显现

UI 按钮回调(不支持 async)

onError 回调的协程

按钮回调是同步的

带转换的顺序操作

ContinueWith 链式调用

避免嵌套 await;自动传播错误

进度条或加载遮罩

协程轮询 进度

yield return null 每帧循环

组件生命周期作用域

destroyCancellationToken

零样板代码;自动清理

用户触发的取消(按钮)

operation.Cancel()

无需 CTS 的直接句柄控制

连续数据流

await foreach + await using

IAsyncEnumerable + 保证释放


使用示例

示例 1——带进度条和取消按钮的加载遮罩

一个医疗培训模拟在会话连接时显示加载遮罩,并提供可视化进度条和取消按钮,供希望在会话开始前退出的学习者使用。

示例 2——将转录令牌流式传输到自定义日志控件

一个企业入职模拟会从 Convai 流式传输单个转录令牌,并将其一次一个令牌地追加到自定义日志控件中,形成打字机效果。


故障排查

症状
可能原因
修复方法

操作保持在 运行中 中,且一直持续

等待永远不会到达的响应的 SDK 方法(网络超时)

设置一个 CancellationToken 带超时的: new CancellationTokenSource(TimeSpan.FromSeconds(15)).Token

HasErrortrueConvaiOperationException 不会被抛出

使用协程路径——错误会传递给 onError 回调,而不会抛出

添加一个 onError 回调到 ToCoroutine()

catch (ConvaiOperationException) 在取消时不会进入该代码块

取消会抛出 OperationCanceledException,而不是 ConvaiOperationException

添加一个单独的 catch (OperationCanceledException) 代码块

在之后取消没有效果 operation.Cancel()

在调用取消之前操作已完成

检查 IsCompleted 在调用 Cancel()

场景卸载时流挂起

ReadAllAsync 循环未传入一个 CancellationToken

传入 destroyCancellationTokenReadAllAsync

ContinueWith 选择器从不运行

源操作失败;错误会被传播,选择器会被跳过

检查链式操作的 HasError 或在 ConvaiOperationException 处捕获


下一步

有关这些模式背后的完整类型参考,请参见 操作与流类型。对于返回 IConvaiOperation<T>的 SDK 方法,请参见 ConvaiManager API角色与玩家 API.

最后更新于

这有帮助吗?