上一篇文章 (C# 使用 Azure.Storage.Queues
寫入佇列(Queue) + 取得資料 )我們談到了簡單操控 Azure Queue ,當作一個可以跨機器跨系統的 Queue 的實作方式,傳統很多時候會用到 Redis 來解決,但是用這應該便宜很多
不過上篇文章說到,他有一個問題,就是你取用後,如果時間沒有到他只會紀錄取用次數跟一般你理解的 Dequeue 不太一樣。

首先,其實在 SendMessage 可以傳入一個參數 visibilityTimeout 這是代表在一個時間後可以顯示,所以我就設計一個案例
我先寫入十筆資料都顯示延遲五秒後再出現,之後再寫入200筆立即出現的資料(但是我有延遲一秒寫一筆為了方便觀測),之後有一個執行緒是一直做 ReceiveMessage的動作
1. 寫入資料
private static void TestEnqueueDataWithVisibilityTimeout()
{
var queueName = "test-azure-queue";
var queue = new Azure.Storage.Queues.QueueClient(ConnectionString, queueName);
queue.CreateIfNotExists();
//寫入十筆資料,並且延遲五秒後再出現
for (var i = 1; i <= 10; i++)
{
var res = queue.SendMessage("延遲執行 " + i + "," + DateTime.Now.ToString(), visibilityTimeout: new TimeSpan(0, 0, 5));
}
//之後執行連續寫入馬上出現的,沒有設定延遲出現
for (var i = 1; i <= 200; i++)
{
var res = queue.SendMessage("馬上執行 " + i + "," + DateTime.Now.ToString()).Value;
System.Threading.Thread.Sleep(1000);
}
}
2.讀取資料
private static void TestDequeueData()
{
var queueName = "test-azure-queue";
for (var i = 1; i <= 300; i++)
{
var queue = new Azure.Storage.Queues.QueueClient(ConnectionString, queueName);
var res = queue.ReceiveMessage().Value;
if (res != null)
{
Console.WriteLine("查詢=>" + res.Body.ToString());
}
else
{
Console.WriteLine("NO DATA!!");
}
System.Threading.Thread.Sleep(millisecondsTimeout: 1000);
}
}
3.呼叫
new Thread(() =>
{
TestDequeueData();
}).Start();
new Thread(() =>
{
TestEnqueueDataWithVisibilityTimeout();
}).Start();
結果
NO DATA!!
查詢=>馬上執行 1,2022/8/12 下午 02:17:44
查詢=>馬上執行 2,2022/8/12 下午 02:17:46
查詢=>馬上執行 3,2022/8/12 下午 02:17:47
查詢=>馬上執行 4,2022/8/12 下午 02:17:48
查詢=>馬上執行 5,2022/8/12 下午 02:17:49
查詢=>延遲執行 1,2022/8/12 下午 02:17:44
查詢=>延遲執行 2,2022/8/12 下午 02:17:44
查詢=>延遲執行 3,2022/8/12 下午 02:17:44
查詢=>延遲執行 4,2022/8/12 下午 02:17:44
查詢=>延遲執行 5,2022/8/12 下午 02:17:44
查詢=>延遲執行 6,2022/8/12 下午 02:17:44
查詢=>延遲執行 7,2022/8/12 下午 02:17:44
查詢=>延遲執行 8,2022/8/12 下午 02:17:44
查詢=>延遲執行 9,2022/8/12 下午 02:17:44
查詢=>延遲執行 10,2022/8/12 下午 02:17:44
查詢=>馬上執行 6,2022/8/12 下午 02:17:50
查詢=>馬上執行 7,2022/8/12 下午 02:17:51
查詢=>馬上執行 8,2022/8/12 下午 02:17:52
查詢=>馬上執行 9,2022/8/12 下午 02:17:53
查詢=>馬上執行 10,2022/8/12 下午 02:17:54
查詢=>馬上執行 11,2022/8/12 下午 02:17:55
查詢=>馬上執行 12,2022/8/12 下午 02:17:56
查詢=>馬上執行 13,2022/8/12 下午 02:17:57
查詢=>馬上執行 14,2022/8/12 下午 02:17:58
查詢=>馬上執行 15,2022/8/12 下午 02:17:59
查詢=>馬上執行 16,2022/8/12 下午 02:18:00
查詢=>馬上執行 17,2022/8/12 下午 02:18:02
查詢=>馬上執行 18,2022/8/12 下午 02:18:03
查詢=>馬上執行 19,2022/8/12 下午 02:18:04
查詢=>馬上執行 20,2022/8/12 下午 02:18:05
...
下面省略

因為一開始寫入的資料都延遲了五秒,所以再立即的佇列部分會被先取出來,一直到被延遲的資料時間到了就會出現
這設計可以應用在一些地方,像是限時開始搶票的東西,大概就先寫到這之後有些心得我再繼續分享..
reference:
https://docs.microsoft.com/zh-tw/dotnet/api/azure.storage.queues.queueclient.sendmessage?view=azure-dotnet#azure-storage-queues-queueclient-sendmessage(system-binarydata-system-nullable((system-timespan))-system-nullable((system-timespan))-system-threading-cancellationtoken)