事务性接收超时

时间:2012-09-21 13:51:41

标签: c# .net transactions msmq message-queue

我有一个从消息队列中读取消息列表的方法。签名是:

IList<TMsg> Read<TMsg>(MessageQueue queue, int timeout, MessageQueueTransaction tx);

基本功能是,它将使用给定的事务在超时内从队列中读取尽可能多的消息。我遇到的问题是决定如何最好地执行超时。我目前有两个工作版本。这些是:

  • 使用BeginPeek超时。如果成功,则使用事务性Receive调用删除该消息。每次调用后,将根据Read开始的时间和当前时间重新计算BeginPeek的超时。
  • 使用具有超时值的Receive,并在超时到期时捕获异常。

第一种方法的问题是它需要在DenySharedReceive模式下读取队列,否则您无法保证Peek和Receive之间的消息仍然存在。第二种方法的问题是需要抛出和处理异常(虽然是内部和透明的),这可能不是一个很好的设计,因为每次调用总是在异常中结束只在特殊情况下抛出异常的想法。

有没有人有任何其他建议我如何实现这一点,或对这两种技术和我的关注点发表评论?

2 个答案:

答案 0 :(得分:1)

您可以使用reactive excensions创建消息生成器,使用Observable.Buffer来管理超时,然后订阅此生成器

public IEnumerable<Message> GetMessage()
{
    //do the peek and receive a single message
    yield return message;
}

//and then something like
var producer = GetMessage().ToObservable();

// this is where your timeout goes
var bufferedMessages = producer.Buffer(TimeSpan.FromSeconds(3));

var disp = bufferedMessages.Subscribe(messages =>
    {
        Console.WriteLine("You've got {0} new messages", messages.Count());
        foreach (var message in messages)
            Console.WriteLine("> {0}", message); // process messages here
    });

disp.Dispose(); // when you no longer want to subscribe to the messages

对于更具反应性的示例,请查看here

答案 1 :(得分:0)

经过一番调查后,至少就.NET而言,Hatchet的评论最接近'回答'。包装的本机方法为'TIMEOUT'提供了返回值(而不是错误值),但这被.NET视为例外,重新包装本机代码是不值得的。我试过了。 :P