我有两个程序,一个是客户端,另一个是客户端的服务器。 客户端像这样将一些数据发送到服务器,然后读取响应:
idtcpclient1.WriteLn(command); //Command contains data that the server needs eg. name and surname
progressbar1.StepIt;
sresult := idtcpclient1.ReadLn();
然后,服务器读取该行,对其进行操作并创建SQL查询。
adoquery1.Close;
adoquery1.SQL.Text := 'select * from '+sGrade;
adoquery1.Open;
但是一旦打开与数据库的连接,客户端就会发出错误" Connection正常关闭"
我已经通过模拟输入测试了没有客户端的服务器代码,并且工作正常。
我认为Indy和AdoQuery存在冲突 如果是这样,为什么以及如何解决它
如果没有那么问题是什么?我该如何解决?
答案 0 :(得分:2)
ADO使用与创建它们的线程具有亲缘关系的单元线程COM对象。它们不能跨越线程边界使用,除非它们被编组。
Indy的TCP服务器是多线程的。每个客户端都在自己的线程中运行。
线程必须调用CoInitialize/Ex()
才能建立与COM的关系,然后才能访问任何COM对象,并在使用COM完成后调用CoUninitialize()
。
您的服务器失败,因为它引发了一个未被捕获的异常,导致客户端断开连接。很可能是因为你没有初始化COM。
您需要基于每个客户端创建ADO对象,不要在主线程中使用它们。在服务器的OnConnect
活动中,请致电CoInitialize/Ex()
。在OnDisconnect
事件中,请致电CoUninitialize()
。在OnExecute
事件中,根据需要动态创建和使用新的ADO对象。
这意味着每个客户端都需要自己的数据库连接。如果您不希望这样,那么将您的ADO逻辑移动到客户端可以在需要时发布请求的专用线程。远离主线程中的数据库工作,它不属于那里。
答案 1 :(得分:0)
如果使用数据模块:您可以为每个客户端创建一个数据模块实例,以避免线程错误。 Indy可以在上下文中保存对客户端数据模块的引用。或者使用数据模块实例池,具体取决于可用资源和流量。