使线程使用中央数据库连接的正确方法

时间:2012-02-13 23:32:37

标签: multithreading delphi service

我正在Delphi XE2中构建一个多线程服务应用程序。除了其他线程之外,每个线程都有自己的用途。主服务线程仅负责保持其他线程的运行并保存日志文件等。这些线程中的每一个都通过同步事件触发器报告回主服务线程。这些线程在服务启动时创建,在服务结束时销毁。

我想引入一个单独的线程作为集中式数据库连接,以避免创建TADOConnection的许多实例。我的服务代码可以调用标准函数,例如UserListDataSet := DBThread.GetUserList(SomeUserListDataSet);,如果我可以发送像SomeDataSet := DBThread.Get(MySqlText);这样的直接SQL语句,那也很好。我也想避免过多CoInitialize()等场合。

作业线程需要使用此db线程。我需要弄清楚如何“询问”某些数据,“等待”响应,并在请求它的线程中“获取”该响应。我确信有很多方法,但我需要知道哪一个最适合我的场景。 Windows消息?活动?我应该有某种排队吗?它应该发送数据集还是别的什么?有没有可以做到这一点的东西?我需要弄清楚如何以可以从其他线程重用的方式构造这个DB线程。

结构如下:

+ SvcThread
  + DBThread
    + TADOConnection
  + Thread1
  + Thread2
  + Thread3

我需要线程1 2和3来向DBThread发送请求。当一个线程向它发送任何请求时,它需要等到它得到响应。一旦有响应,数据库线程需要通知请求线程。每个线程也可以同时向此DB线程发送请求。

如何实现这一目标的好教程将是完美的 - 它只需要适合我的场景。我不需要只知道“如何让两个线程一起讨论”,而是“如何使许多线程与集中式数据库线程通信”。这些作业线程是作为主服务线程的子项创建的,并不归db线程所有。 db线程不知道作业线程。

3 个答案:

答案 0 :(得分:6)

通常,您有一个请求队列,其中存储了所有请求。数据库线程从队列中读取请求,处理它,然后调用请求者指定的回调例程来处理结果。不确定这如何映射到Delphi范例,但基础应该是相同的。

答案 1 :(得分:3)

执行任何"请求"线程在等待从数据库获取响应时有什么可盈利的东西?如果答案是"否,"因为我怀疑它很可能是,所以也许你可以通过消除对数据库线程的需求来简化你的情况。完全。也许所有线程都可以依次共享一个数据库连接,使用互斥对象让他们等待轮到他们。"

在这种情况下,会有一个数据库连接,任何需要使用它的线程都会这样做。但是他们必须首先获取一个互斥对象,在他们进行数据库查询期间保持互斥锁,然后释放互斥锁,以便下一个线程可以轮到它。

如果您认为将线程专用于管理连接在某种程度上是有利的(或必要性......),那么也许您可以使用(a)一个互斥体来序列化来实现结果这些要求和以前一样;和(b)一个事件对象,用于通知DB线程已发布新请求,(c)另一个事件对象,用于通知请求者请求已经完成。

在任何一种情况下,如果你确实确定请求者线程没有任何有用的东西,他们可以在此期间做,你有线程"只是睡觉"直到轮到他们。然后,他们直接或间接地开展业务。没有"队列,"没有复杂的共享数据结构,只是因为你(比如......)确定不需要它们。

答案 2 :(得分:3)

我认为使用数据库连接池更适合您的问题。这也允许您以后扩展应用程序,而不必创建额外的数据库线程,然后必须为这些数据库线程管理“负载平衡”。

由于您提到使用TADOConnection,请查看Cary Jensen http://cc.embarcadero.com/item/19975所做的此实现。 我在几个应用程序中成功使用此数据库连接池。我已经通过多种方式对其进行了修改,包括使用ini文件来控制:最大连接数,清理时间,超时时间等。

Cary撰写了几篇文章作为文档。一个是http://edn.embarcadero.com/article/30027