如何每隔X秒从Service Bus队列批量处理消息

时间:2015-05-23 18:07:44

标签: c# azure message-queue servicebus azure-servicebus-queues

我的服务总线队列以前一次处理过一条消息。 我想更改它以允许邮件排队,这样我就可以每隔X秒批量处理它们。我最初这样做了:

var messagingFactorySettings = new MessagingFactorySettings
{
    NetMessagingTransportSettings = { 
        BatchFlushInterval = TimeSpan.FromMilliseconds(10000) },
        TokenProvider = credentials
};

现在我想接收这些消息,但似乎我必须在循环中做到这一点,以获得它们:

while ((messages = myQueueClient.ReceiveBatch(1000).ToList()) != null)
{
    foreach (var message in messages)
    { ...

据我了解,BatchFlushInterval允许请求在X时间内建立,这样我就不会逐个接收消息,而是批量接收消息。因此,我不确定为什么我不能像以前那样做一些事情:

myQueueClient.OnMessage((m) =>
{

但是批量版本:

myQueueClient.OnBulkMessage((listOfMessages) =>
{

我是否遗漏了某些内容或是否一直在轮询实现这一目标的唯一方法?我的BatchFlushInterval似乎也被忽略了。我希望它只会每隔10秒检查一次新邮件,但它会立即收到第一批邮件,并且所有新邮件也会立即得到处理。

假设我希望每个X(即:1)秒从队列中拉出Y消息(即:1000)并立即处理它们,我将如何做到这一点? 为什么BatchFlushInterval没有任何影响吗?

1 个答案:

答案 0 :(得分:1)

看起来似乎是一个简单的Thread.Sleep(x)

我发现暂停的问题直到总有一段时间过去很有趣,所以我开始实施一个秒表子类,使问题以更清晰,更易读的方式解决。

while ((var messages = myQueueClient.ReceiveBatch(1000)) != null)
{
    var sw = WaitableStopwatch.StartNew();

    // ReceiveBatch() return IEnumerable<>. No need for .ToList().
    foreach (var message in messages)
    {
        ...
    }

    // If processing took less than 10 seconds, sleep
    // for the remainder of that time span before getting
    // the next batch.
    sw.Wait(Timespan.FromSeconds(10));
}



/// <summary>
/// Extends Stopwatch with the ability to wait until a specified
/// elapsed time has been reached.
/// </summary>
public class WaitableStopwatch : Stopwatch
{
    /// <summary>
    /// Initializes a new WaitableStopwatch instance, sets the elapsed
    /// time property to zero, and starts measuring elapsed time.
    /// </summary>
    /// <returns>A WaitableStopwatch that has just begun measuring elapsed time.</returns>
    public static new WaitableStopwatch StartNew()
    {
        WaitableStopwatch sw = new WaitableStopwatch();

        sw.Start();

        return sw;
    }

    /// <summary>
    /// Waits until the ElapsedMilliseconds property reaches <paramref name="elapsedMilliseconds"/>.
    /// </summary>
    /// <param name="elapsedMilliseconds"></param>
    public void Wait(int elapsedMilliseconds)
    {
        Wait(TimeSpan.FromMilliseconds(elapsedMilliseconds));
    }

    /// <summary>
    /// Waits until when the Elapsed property reaches <paramref name="elapsed"/>.
    /// </summary>
    /// <param name="elapsed"></param>
    public void Wait(TimeSpan elapsed)
    {
        TimeSpan diff;

        while ((diff = elapsed - this.Elapsed) > TimeSpan.Zero)
        {
            Thread.Sleep(diff);
        }
    }

    /// <summary>
    /// Waits until when the ElapsedMilliseconds property reaches <paramref name="elapsedMilliseconds"/>.
    /// </summary>
    /// <param name="elapsedMilliseconds"></param>
    public Task WaitAsync(int elapsedMilliseconds)
    {
        return WaitAsync(TimeSpan.FromMilliseconds(elapsedMilliseconds));
    }

    /// <summary>
    /// Waits until when the Elapsed property reaches <paramref name="elapsed"/>.
    /// </summary>
    /// <param name="elapsed"></param>
    public async Task WaitAsync(TimeSpan elapsed)
    {
        TimeSpan diff;

        while ((diff = elapsed - this.Elapsed) > TimeSpan.Zero)
        {
            await Task.Delay(diff);
        }
    }
}