Indy Server和AdoQuery是冲突的

时间:2014-06-19 14:38:07

标签: sql delphi delphi-7 indy tadoquery

我有两个程序,一个是客户端,另一个是客户端的服务器。 客户端像这样将一些数据发送到服务器,然后读取响应:

 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存在冲突 如果是这样,为什么以及如何解决它

如果没有那么问题是什么?我该如何解决?

2 个答案:

答案 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可以在上下文中保存对客户端数据模块的引用。或者使用数据模块实例池,具体取决于可用资源和流量。