Oracle AQ与ODP.Net。连接时自动出列

时间:2012-04-27 15:19:01

标签: oracle odp.net oracle-aq

我正在使用Oracle ODP.Net进行入队和出队。

过程A:入队 进程B:使用MessageAvailable事件出列队列

如果进程A和B正在运行,则没有问题。在“过程B”中,事件总是被触发。

但是,如果“进程B”关闭且“进程A”打开,则当“进程B”重新启动时,在关闭时间内插入的队列将丢失。

是否可以选择为过去插入的所有队列触发事件?

非常感谢

2 个答案:

答案 0 :(得分:3)

似乎有两种方法可以解决这个问题:

  1. 调用OracleAQQueue类的Listen()方法(在注册消息通知之后)以获取位于队列中的“孤立”消息。请注意,Listen()会阻塞,直到收到消息或发生超时。因此,如果队列中没有消息,您需要指定(短)超时以返回处理线程。
  2. 调用Dequeue()方法并捕获Oracle错误25228(没有可用于出队的消息)。请参阅Oracle支持论坛的以下主题:https://forums.oracle.com/forums/thread.jspa?threadID=2186496
  3. 我一直在讨论这个话题。如果您仍然需要“手动”测试新消息,那么首先使用MessageAvaiable事件回调有什么好处?我考虑的一条路线是将Listen()方法包装在异步调用中,以便调用者不会在线程上阻塞(直到收到消息或发生超时)。我在自定义的Receive()方法中包装了Listen()和Dequeue(),并创建了自己的MessageReceived事件处理程序,以将消息详细信息传递给调用线程。看起来有点多余,因为ODP.NET提供了开箱即用的回调,但我不必处理你描述的问题(或者编写代码来“手动”测试“孤立”消息。

    欢迎任何关于方法的意见/想法。

答案 1 :(得分:0)

我一直在看这个,最后做了类似Greg的事情。我没有使用过Listen()方法,因为我认为它不能为我提供任何超越简单的Dequeue() - 当你想要代表多个消费者监听时,Listen()似乎是有益的,我的实例不相关(见Oracle Docs)。

因此,在我的“进程B”中,我首先在启动轮询过程之前注册通知,以检查是否存在任何现有消息。它不是Listen(),它只是在一个受控循环中调用Dequeue(),并设置了几秒钟的等待时间。如果轮询进程遇到Oracle超时,则等待期已过,并且轮询停止。如果等待时间尚未到期,我可能需要考虑处理超时(尽管如果可能发生这种情况,并非100%确定)。

我注意到在轮询时排队的任何消息都会调用消息通知方法,但是当它连接并尝试检索消息时,轮询过程似乎总是采用它。因此,在消息通知方法中,我捕获并忽略编号为25263(no message in queue <...> with message ID <...>)的任何OracleExceptions。