0

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

 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;

但是一旦打开与数据库的连接,客户端就会给出错误“连接正常关闭”

我通过模拟输入测试了没有客户端的服务器代码,它工作正常。

我认为 Indy 和 AdoQuery 有冲突如果是这样,为什么以及如何解决它

如果不是,那是什么问题,我应该如何解决?

4

2 回答 2

2

ADO 使用与创建它们的线程有关联的单元线程 COM 对象。除非它们被编组,否则它们不能跨线程边界使用。

Indy 的 TCP 服务器是多线程的。每个客户端都在自己的线程中运行。

线程必须调用CoInitialize/Ex()以建立其与 COM 的关系,然后才能访问任何 COM 对象,并CoUninitialize()在使用 COM 完成时调用。

您的服务器失败,因为它引发了一个断开客户端的未捕获异常。很可能是因为您没有初始化 COM。

您需要基于每个客户端创建 ADO 对象,不要在主线程中使用它们。在服务器OnConnect事件中,调用CoInitialize/Ex(). 在这种情况OnDisconnect下,调用CoUninitialize(). 在这种情况OnExecute下,根据需要动态创建和使用新的 ADO 对象。

这确实意味着每个客户端都需要自己的数据库连接。如果您不希望这样,则将您的 ADO 逻辑移动到专用线程,客户端可以在需要时将请求发布到该线程。远离在主线程中做数据库工作,它不属于那里。

于 2014-06-19T15:29:47.513 回答
0

如果您使用数据模块:您可以为每个客户端创建一个数据模块实例,以避免线程错误。Indy 可以在上下文中保存对客户端数据模块的引用。或者根据可用资源和流量使用数据模块实例池。

于 2014-06-19T14:54:22.027 回答