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

如何在返回前等待回调?Unity C# HttpClient移植技术问题

解决Unity中HttpClient回调异步与同步返回的冲突问题

你遇到的核心问题是:.NET原生HttpClient可以用GetAsync().Result同步阻塞等待结果,但Unity使用的第三方HttpClient(看起来是CI.HttpClient这类)是基于回调的异步模型,直接同步返回的话,回调还没触发就已经返回空值了。

为什么同步返回行不通?

Unity的主线程负责渲染和处理用户输入,不能被长时间阻塞。而Unity的HttpClient回调是在后续的帧中执行的,当你在GetToBackOffice里直接return idProcess时,回调逻辑还没跑,所以idProcess肯定是空的。

你的现有实现分析

你已经尝试用协程解决,思路是对的,但用全局response变量加轮询的方式可以进一步优化,避免耦合和不必要的性能消耗。

优化后的实现方案

1. 封装工具类:提供协程和回调两种异步方式

我们可以把Http请求逻辑封装成静态工具类,同时支持协程等待和回调返回,适配不同场景:

using CI.HttpClient;
using Newtonsoft.Json.Linq;
using UnityEngine;
using System;

public static class Utils
{
    private const string backOfficeUrl = "http://myurl/api/";

    // 定义回调委托,用于异步返回结果
    public delegate void GetBackOfficeResultCallback(JObject result);

    /// <summary>
    /// 异步请求后台接口,通过回调返回结果
    /// </summary>
    public static void GetToBackOfficeAsync(string action, GetBackOfficeResultCallback callback)
    {
        var fullUrl = backOfficeUrl + action;
        var httpClient = new HttpClient();

        httpClient.GetString(new Uri(fullUrl), (response) =>
        {
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var result = JObject.Parse(response.Data);
                callback?.Invoke(result);
            }
            else
            {
                Debug.LogError($"请求失败: {response.StatusCode} - {response.ReasonPhrase}");
                callback?.Invoke(null);
            }
        });
    }

    /// <summary>
    /// 协程版本:可以在MonoBehaviour中yield等待请求完成
    /// </summary>
    public static IEnumerator GetToBackOfficeCoroutine(string action, Action<JObject> onCompleted)
    {
        bool isRequestFinished = false;
        JObject requestResult = null;

        // 发起异步请求,在回调中标记完成并赋值结果
        GetToBackOfficeAsync(action, (result) =>
        {
            requestResult = result;
            isRequestFinished = true;
        });

        // 等待请求完成:用WaitUntil替代固定时间轮询,更高效
        yield return new WaitUntil(() => isRequestFinished);

        // 回调返回结果
        onCompleted?.Invoke(requestResult);
    }
}

2. 在MonoBehaviour中使用协程处理业务逻辑

在你的EventHubSimulator中,通过协程等待Http请求完成后,再执行后续业务代码:

using UnityEngine;
using Newtonsoft.Json.Linq;

public class EventHubSimulator : MonoBehaviour
{
    void Start()
    {
        // 填充参数
        string oId = "你的ID";
        string secretKey = "你的密钥";
        FakeData vh = new FakeData();

        // 启动协程处理请求和后续逻辑
        StartCoroutine(ProcessSendData(oId, secretKey, vh));
    }

    private IEnumerator ProcessSendData(string id, string secretKey, FakeData data)
    {
        JObject idProcess = null;

        // 等待Http请求完成,拿到结果
        yield return Utils.GetToBackOfficeCoroutine($"Events/{id}/infos", (result) =>
        {
            idProcess = result;
        });

        // 现在idProcess已经有值了,执行后续逻辑
        if (idProcess != null)
        {
            Debug.Log($"成功获取到后台数据: {idProcess.ToString()}");
            // 这里写你需要用idProcess处理的业务代码
            // ...
        }
        else
        {
            Debug.LogError("获取后台数据失败");
        }
    }
}

// 你的FakeData类示例
public class FakeData { }

关键优化点

  • 避免全局变量:用闭包和回调传递结果,降低代码耦合
  • 高效等待:用WaitUntil替代固定时间轮询,请求完成后立即继续执行,减少不必要的性能消耗
  • 清晰的错误处理:用Debug.LogError输出错误信息,方便调试
  • 灵活的API:同时提供异步回调和协程版本,适配不同业务场景

核心原则

在Unity中处理异步操作,绝对不要用同步阻塞的方式等待回调(比如死循环等待变量赋值),这会卡死主线程导致游戏假死。协程是Unity官方推荐的异步处理方式,它可以让代码逻辑看起来像同步的,但实际上是在帧间隙执行,不会阻塞主线程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:33:25