如何从C# Thread线程中获取返回值并用于后续条件判断
问题原因
你新启动的Thread线程和当前接口的主线程是并行执行的,主线程不会等待子线程内的短信发送逻辑执行完成,就会直接运行后续的if(data=="Pending")判断。此时子线程还没完成对data变量的赋值,data还是初始的空字符串,所以必然会进入else分支。
解决方案
方案1:用Join()方法让主线程等待子线程执行完成(适配现有代码改动最小)
在启动线程之后调用Join(),强制主线程阻塞等待短信发送逻辑执行完成、data赋值完成后再往下执行判断逻辑,修改后的代码如下:
public ActionResult Registration(VMAccount vm) { try { var existUser = accountBusiness.GetPhoneData(vm.Mobile); if (existUser.Count == 0) { string data = ""; vm.Role = AppRole.Consumer; int retValue = accountBusiness.ConsumerRegistration(vm); if (retValue == 1) { Thread smsThread = new Thread(() => { data = sms.SendRegistrationOtp(vm.Mobile); }); smsThread.Start(); // 新增代码:等待短信发送线程执行完成,再往下执行 smsThread.Join(); } if(data=="Pending") { return Json(2, JsonRequestBehavior.AllowGet); } else { return Json(3, JsonRequestBehavior.AllowGet); } } else { return Json(1, JsonRequestBehavior.AllowGet); } } catch (Exception ex) { log.Error("Admin-InsertAccountDetails", ex); return Json(0, JsonRequestBehavior.AllowGet); } }
方案2:用Task替代Thread(更推荐的写法,性能和灵活性更高)
如果你的项目框架支持,更建议用Task来实现异步逻辑等待,写法更简洁,后续也可以很方便的改成异步控制器接口来避免线程阻塞:
// 同步等待版本,改动最小 public ActionResult Registration(VMAccount vm) { try { var existUser = accountBusiness.GetPhoneData(vm.Mobile); if (existUser.Count == 0) { string data = ""; vm.Role = AppRole.Consumer; int retValue = accountBusiness.ConsumerRegistration(vm); if (retValue == 1) { // 用Task.Run启动异步逻辑,调用Wait()等待执行完成 Task.Run(() => { data = sms.SendRegistrationOtp(vm.Mobile); }).Wait(); } if(data=="Pending") { return Json(2, JsonRequestBehavior.AllowGet); } else { return Json(3, JsonRequestBehavior.AllowGet); } } else { return Json(1, JsonRequestBehavior.AllowGet); } } catch (Exception ex) { log.Error("Admin-InsertAccountDetails", ex); return Json(0, JsonRequestBehavior.AllowGet); } }
如果你的项目支持异步控制器,还可以改成无阻塞的异步写法,性能更好:
// 异步接口版本 public async Task<ActionResult> Registration(VMAccount vm) { try { var existUser = await accountBusiness.GetPhoneDataAsync(vm.Mobile); if (existUser.Count == 0) { string data = ""; vm.Role = AppRole.Consumer; int retValue = await accountBusiness.ConsumerRegistrationAsync(vm); if (retValue == 1) { data = await Task.Run(() => sms.SendRegistrationOtp(vm.Mobile)); } if(data=="Pending") { return Json(2, JsonRequestBehavior.AllowGet); } else { return Json(3, JsonRequestBehavior.AllowGet); } } else { return Json(1, JsonRequestBehavior.AllowGet); } } catch (Exception ex) { log.Error("Admin-InsertAccountDetails", ex); return Json(0, JsonRequestBehavior.AllowGet); } }
额外注意
如果你原本开线程的目的是不想让短信发送逻辑阻塞接口返回,那你就不能在当前接口的返回逻辑里依赖短信发送的结果,这种场景需要调整业务逻辑:比如先返回注册成功的状态,短信发送结果后续通过站内通知、或者前端轮询接口的方式获取。
内容的提问来源于stack exchange,提问作者Pavith Shan
相关产品推荐
相关产品推荐

