Unity:不使用Thread.Sleep等待StartCoroutine完成后返回Login结果
解决Unity协程异步导致Login方法提前返回的问题
核心问题是同步方法无法等待异步协程完成:Login是同步方法,启动协程后会立刻执行return语句,而HttpPost的回调要等网络请求完成才会触发,所以返回的testing是未被正确赋值的初始值。
以下是两种不需要Thread.Sleep的可行解决方案:
方案一:改用回调模式(Unity传统异步写法)
把Login改成不直接返回结果,而是传入一个回调函数,等网络请求完成后再通过回调返回登录结果:
public void Login(string LoginName, string username, string password, Action<bool> onLoginComplete) { RequestHeader contentTypeHeader = new RequestHeader { Key = "Content-Type", Value = "application/json" }; JsonData data = new JsonData(); data["username"] = username; data["password"] = password; // 启动协程发起请求,在回调中处理结果并调用传入的登录完成回调 StartCoroutine(NetworkManage.Instance.HttpPost(tempapiConfig[LoginName], data.ToJson(), (r) => { bool loginResult = OnRequestLoginComplete(r); onLoginComplete?.Invoke(loginResult); }, new List<RequestHeader> { contentTypeHeader })); } bool OnRequestLoginComplete(Response response) { Debug.Log($"Status Code: {response.StatusCode}"); Debug.Log($"Data: {response.Data}"); Debug.Log($"Error: {response.Error}"); return true; }
调用示例:
// 调用Login时传入回调处理结果 Login("你的登录接口Key", "用户名", "密码", (isSuccess) => { // 这里拿到最终登录结果做后续处理 Debug.Log($"登录结果:{isSuccess}"); });
方案二:使用async/await(Unity 2017.1+支持)
利用Unity对Task的支持,把Login改成异步方法,通过TaskCompletionSource等待协程完成:
public async Task<bool> Login(string LoginName, string username, string password) { var taskCompletionSource = new TaskCompletionSource<bool>(); RequestHeader contentTypeHeader = new RequestHeader { Key = "Content-Type", Value = "application/json" }; JsonData data = new JsonData(); data["username"] = username; data["password"] = password; StartCoroutine(NetworkManage.Instance.HttpPost(tempapiConfig[LoginName], data.ToJson(), (r) => { bool loginResult = OnRequestLoginComplete(r); taskCompletionSource.SetResult(loginResult); }, new List<RequestHeader> { contentTypeHeader })); // 等待协程完成后返回结果 return await taskCompletionSource.Task; } bool OnRequestLoginComplete(Response response) { Debug.Log($"Status Code: {response.StatusCode}"); Debug.Log($"Data: {response.Data}"); Debug.Log($"Error: {response.Error}"); return true; }
调用示例(需要在async方法内调用):
// 在异步方法中通过await等待登录结果 async void SomeAsyncMethod() { bool loginResult = await Login("你的登录接口Key", "用户名", "密码"); // 处理登录结果 }
注意事项
- 绝对不能用
Thread.Sleep,因为会阻塞Unity主线程,导致游戏冻结、无响应。 - 方案一适合所有Unity版本,是Unity最常用的异步处理方式;方案二更符合C#现代异步编程习惯,但需要Unity版本支持。
内容的提问来源于stack exchange,提问作者aron kan
相关产品推荐
相关产品推荐

