restful 服务器一个问题,看ChatGPT的威力
看看是否牛逼:
真不是写代码的料,也没有这样的天赋,仅仅玩玩而已。
问题:客户端边缘路由中一段js代码,使用get请求一个方法,把json数据送入数据库相关表。由于种种原因导致长连接,通过资源管理器可以看到TCP连接一直挂在那里。(该问题不知道是否是伪命题,请专业人员指导)
七搞八搞,依赖Chatgpt才(应该)搞定了,否则永远不可能,如果不是永远,那么就是非常非常遥远、遥远、遥远......。
上代码:
function TUsegear.UpdateAJson2DB4ZT(aJson: string): string; //提交Json数组到账套表 var Task: ITask; //用于执行异步任务 TimeoutMs: Integer; //超时时间,单位:毫秒(默认 5000ms = 5s) TaskCompletedFlag: Integer; // ✅ 确保 TInterlocked.Exchange 线程安全 任务完成标志(0 = 未完成,1 = 已完成),用于确保线程安全 TaskResult: string;// 最终返回的执行结果 TaskEvent: TEvent; //用于通知主线程任务完成,避免 Sleep(10); 造成的 CPU 轮询 begin Result := 'Timeout'; TimeoutMs := 10000; TaskCompletedFlag := 0; // 0 = False, 1 = True // 任务开始时标记为未完成 TaskResult := 'Timeout'; TaskEvent := TEvent.Create(nil, True, False, ''); //启动后台任务 Task := TTask.Run(procedure var LocalQuery: TFDQuery; LocalConn: TFDConnection; ja: TJSONArray; jo: TJSONObject; LocalResult, ZTName, myTable, aSQL: string; begin LocalResult := 'Unknown Error'; ja := nil; LocalConn := TFDConnection.Create(nil); LocalQuery := TFDQuery.Create(nil); try try LocalConn.DriverName := FDConnection1.DriverName; LocalConn.Params.Assign(FDConnection1.Params); // **确保复制密码和数据库信息** LocalConn.Params.Values['Password'] := FDConnection1.Params.Values['Password']; LocalConn.Params.Values['User_Name'] := FDConnection1.Params.Values['User_Name']; LocalConn.Params.Values['Database'] := FDConnection1.Params.Values['Database']; try LocalConn.Connected := True; // **在任务线程里独立连接数据库** except on E: Exception do begin LocalResult := '线程数据库连接失败: - ' + E.Message; if Var_Log then PostLog(llError,'线程数据库连接失败: -:'+e.Message); Exit; end; end; // 解析 JSON ja := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(aJson), 0) as TJSONArray; if not Assigned(ja) or (ja.Count = 0) then raise Exception.Create('Invalid or empty JSON array'); //获取账套名称 (zt) 和目标表名 (mytable) jo := ja.Items[0] as TJSONObject; ZTName := jo.GetValue<string>('zt'); try LocalConn.Connected := False; // 先确保连接断开 LocalConn.ConnectionDefName := ZTName; LocalConn.Connected := True;//链接指定账套 if Var_Log then PostLog(llHint,'线程账套数据库连接成功'); except on E: Exception do begin if Var_Log then PostLog(llError, '线程账套数据库连接失败: ' + E.Message); Exit; end; end; LocalQuery.Connection := LocalConn; LocalQuery.CachedUpdates := True; myTable := jo.GetValue<string>('mytable'); //把 JSON 转换为数据集 (Dataset) 并提交数据 aSQL := 'SELECT * FROM ' + myTable + ' WHERE 1=2'; LocalQuery.Open(aSQL); TConverter.New.JSON.Source(ja).ToDataSet(LocalQuery); LocalQuery.ApplyUpdates(0); LocalResult := 'OK'; except on E: Exception do begin LocalResult := 'Error: ' + E.Message; if Var_Log then PostLog(llError,LocalResult); end; end; finally if Assigned(ja) then FreeAndNil(ja); FreeAndNil(LocalQuery); FreeAndNil(LocalConn); end; TThread.Synchronize(nil, procedure //线程安全更新 begin if TInterlocked.Exchange(TaskCompletedFlag, 1) = 0 then begin TaskResult := LocalResult; TaskEvent.SetEvent; end; end); end); try //任务超时处理 if not Task.Wait(TimeoutMs) then begin Task.Cancel; TaskEvent.SetEvent; // ✅ 让主线程立即返回 end; except on E: Exception do begin TaskResult := 'Error: Task.Wait failed - ' + E.Message; end; end; //彻底释放 Task if Task.Status <> TTaskStatus.Completed then begin Task.Wait(1000); // 额外等待1秒,确保任务彻底结束 end; if TaskEvent.WaitFor(TimeoutMs) = wrTimeout then begin TaskResult := 'Error: Event timeout reached'; end; TaskEvent.Free; Task := nil; // ✅ 彻底释放 Task,防止意外访问 Result := TaskResult; //主线程返回最终结果 end;