C# 如何每X秒批量处理来自服务总线队列的消息
我的服务总线队列以前一次处理一条消息我想将其更改为允许消息排队,以便每X秒批量处理一次。我最初是这样做的:C# 如何每X秒批量处理来自服务总线队列的消息,c#,azure,message-queue,servicebus,azure-servicebus-queues,C#,Azure,Message Queue,Servicebus,Azure Servicebus Queues,我的服务总线队列以前一次处理一条消息我想将其更改为允许消息排队,以便每X秒批量处理一次。我最初是这样做的: var messagingFactorySettings = new MessagingFactorySettings { NetMessagingTransportSettings = { BatchFlushInterval = TimeSpan.FromMilliseconds(10000) }, TokenProvider = creden
var messagingFactorySettings = new MessagingFactorySettings
{
NetMessagingTransportSettings = {
BatchFlushInterval = TimeSpan.FromMilliseconds(10000) },
TokenProvider = credentials
};
现在我想接收消息,但似乎我必须执行这个无限while循环才能获取它们:
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没有任何影响?看起来一个简单的
线程。睡眠(X)
我发现暂停直到总时间过去的问题很有趣,所以我开始实现一个stopwatch子类,它可以以更清晰、更可读的方式解决这个问题
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);
}
}
}
while((var messages=myQueueClient.ReceiveBatch(1000))!=null)
{
var sw=WaitableStopwatch.StartNew();
//ReceiveBatch()返回IEnumerable。不需要.ToList()。
foreach(消息中的var消息)
{
...
}
//如果处理时间少于10秒,则睡眠
//在到达之前的剩余时间内
//下一批。
软件等待(时间跨度从秒(10));
}
///
///扩展秒表,使其能够等到指定的时间
///已达到运行时间。
///
公共类可等待秒表:秒表
{
///
///初始化一个新的WaitableStopwatch实例,设置运行时间
///时间属性设置为零,并开始测量经过的时间。
///
///一种可等待的秒表,刚开始测量经过的时间。
公共静态新建WaitableStopwatch StartNew()
{
WaitableStopwatch sw=新的WaitableStopwatch();
sw.Start();
返回sw;
}
///
///等待,直到ElapsedMilliseconds属性达到。
///
///
公共无效等待(整数延迟毫秒)
{
等待(TimeSpan.From毫秒(elapsedMilliseconds));
}
///
///等待直到已用属性到达。
///
///
公共无效等待(时间跨度已过)
{
时间跨度差异;
while((diff=appeased-this.appeased)>TimeSpan.Zero)
{
睡眠(差异);
}
}
///
///等待,直到ElapsedMilliseconds属性达到。
///
///
公共任务WaitAsync(整数elapsedMilliseconds)
{
返回WaitAsync(TimeSpan.frommillistics(elapsedmillistics));
}
///
///等待直到已用属性到达。
///
///
公共异步任务WaitAsync(时间跨度已过)
{
时间跨度差异;
while((diff=appeased-this.appeased)>TimeSpan.Zero)
{
等待任务。延迟(差异);
}
}
}
循环只在30秒内输入一次,它会自动抓取新消息,但不会以我设置为BatchFlushInterval的速率发生。即使我要摆脱while循环,编写自己的计时器来调用ReceiveBatch,我认为这应该是不必要的。有了这段代码,计时器将处于30秒延迟之上。这个问题还不完全清楚。你是说ReceiveBatch()需要30秒才能返回,但只返回一条消息,尽管有很多条消息?我更新了我的问题。实际上,如果有新数据,它会自动返回。我设置了一个计时器来不断添加记录,它们会立即得到处理,而不是遵守BatchFlushInterval中的设置。在这种情况下,我的答案似乎应该起作用,显然是在更改为10秒之后。我不知道BatchFlushInterval设置。关于必须使用计时器,您可能是对的。我在网上找到了一个他们做类似事情的链接。我认为BatchFlushInterval只与send和complete方法相关,但我不确定如何进行。如果我找不到内置的解决方案,那么我将标记为答案。