我遇到了一个问题,我的 ConcurrentQueue 在单例中似乎没有以正确的顺序处理项目。我知道它是 FIFO,所以我想也许内存中的队列不一样,或者我的 Dequeue 出了什么问题?我测试的方法是快速向我的 API 端点发出 3 个邮递员请求。如果有人可以帮助我理解为什么这些没有相互运行,我将不胜感激!
截至目前,我倾向于使用 Queue.TryPeek 无法正常工作,因为第二个和第三个请求似乎在第一个请求出列之前排队。
因此,当我运行以下代码时,我会在控制台中看到以下输出。
Queued message: Test 1
Sending message: Test 1
Queued message: Test 2
Sending message: Test 2
Dequeuing message: Test 2
Returning response: Test 2
Queued message: Test 3
Sending message: Test 3
Dequeuing message: Test 1
Returning response: Test 1
Dequeuing message: Test 3
Returning response: Test 3
这是我的 API 控制器方法,它正在获取一条消息并将该消息排队,一旦消息排队,它将等到它在前面看到该请求的消息,然后发送它,然后将其出列。
控制器
[HttpPost]
[Route("message")]
public IActionResult SendMessageUser([FromBody]Message request)
{
Console.WriteLine($"Queued message: {request.Message}");
_messageQueue.QueueAndWaitForTurn(request);
Console.WriteLine($"Sending message: {request.Message}");
var sendMessageResponse = _messageService.SendMessageToUser(request.Name, request.Message);
Console.WriteLine($"Dequeuing message: {request.Message}");
_messageQueue.DequeueMessage(request);
Console.WriteLine($"Returning response: {request.Message}");
return Ok(sendMessageResponse);
}
至于队列,我将它绑定到 IoC,如下所示:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IMessageQueue, MessageQueue>();
services.AddScoped<IMessageService, MessageService>();
services.AddMvc();
}
这是我的队列类单例,我在这里使用单例,因为我希望在应用程序的整个生命周期中只有这个队列的 1 个实例。
public class MessageQueue : IMessageQueue
{
private Lazy<ConcurrentQueue<Message>> _queue =
new Lazy<ConcurrentQueue<Message>>(new ConcurrentQueue<Message>());
public ConcurrentQueue<Message> Queue
{
get
{
return _queue.Value;
}
}
public void QueueAndWaitForTurn(Message message)
{
Queue.Enqueue(message);
WaitForTurn();
}
public bool DequeueMessage(Message message)
{
var messageIsDequeued = Queue.TryDequeue(out message);
return messageIsDequeued;
}
public void WaitForTurn()
{
Message myMessage = null;
var myMessageIsNext = Queue.TryPeek(out myMessage);
while (!Queue.TryPeek(out myMessage))
{
Thread.Sleep(1000);
WaitForTurn();
}
}
}