2012-04-27 35 views
1

我使用Oracle ODP.Net来入队和出队。。自动出队连接

方法A:排队 方法B:与出队事件MessageAvailable

如果过程A和B都在运行,就没有问题。在“流程B”中,事件总是被解雇。

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

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

非常感谢

回答

2

似乎有是解决此问题的两种方法:

  1. 调用OracleAQQueue类的监听()方法来捡(注册为消息通知后),“孤立”消息坐在队列中。请注意,Listen()阻塞直到收到消息或发生超时。所以,如果没有消息在队列中,你会想要指定一个(短)超时返回到处理线程。
  2. 调用Dequeue()方法并捕获Oracle错误25228(没有可用于出队的消息)。请参阅Oracle支持论坛的以下主题:https://forums.oracle.com/forums/thread.jspa?threadID=2186496

我在这个话题上一直在挠头。如果您仍然需要“手动”测试新消息,首先使用MessageAvaiable事件回调有什么好处?我思考的一条路线是将Listen()方法封装在异步调用中,以便调用者不会阻塞该线程(直到收到消息或发生超时)。我在自定义Receive()方法中封装了Listen()和Dequeue(),并创建了自己的MessageReceived事件处理函数,以将消息细节传递给调用线程。似乎有点多余,因为ODP.NET提供了开箱即用的回调,但我不必处理您描述的问题(或编写代码以“手动”测试“孤立”的消息。对方法的意见/想法是欢迎的

0

我一直在看这个,也结束了做一些类似于格雷格我没有使用Listen()方法,虽然我不认为它提供我什么都超过简单的Dequeue() - Listen()似乎是有益的,当你想代表多个消费者听,这在我的例子中是不相关的(见Oracle Docs

因此,过程B'我首先注册在启动轮询过程以检查任何现有消息之前发送通知。它不听(),它只是在一个控制的循环内调用Dequeue(),并设置了几秒钟的等待周期。如果轮询过程遇到Oracle超时,则等待期已过,并停止轮询。如果等待期没有过期,我可能需要考虑处理超时(尽管不是100%确定这是否可能发生)。

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