我正在桌面Windows应用程序上汇总一些简单的检测,我想将有关应用程序中(可能在不同的线程上(发生的事情的消息写入列表或队列,然后定期(按时间或消息数(将它们打包为json消息并转发到服务器。 虽然我可以简单地设置一个计时器,并在每次触发时发送消息组,但必须有一种基于某种设计模式的更简洁的方法。 寻找如何以优雅的方式处理这个问题。 似乎这可能是观察者模式...
我正在寻找简单的东西,不想设置消息队列软件或类似的东西,只是将它们打包并发送到 Web 服务。 谢谢!
如果你想编写自己的代码,你可以将一个列表包装在一个类中,当有足够的消息要发送时,该类处理发送消息。
使用下面的类,您只需创建它的全局实例,然后您的线程就可以调用
Application.MessageQueue.AddMessage($"{timestamp} - {threadName}: Some message");
这只是我的头顶,但该类的简化版本看起来像这样:
class MessageQueue
{
public int MaxQueueSize
{
get { return maxQueueSize; }
set
{
lock (lockObject)
{
// Setting this to < 1 means messages will not be sent automatically
// (the calling application must call 'SendMessages' itself)
if (value < 1) value = int.MaxValue;
maxQueueSize = value;
}
}
}
private int maxQueueSize;
private List<string> unsentMessages;
private readonly object lockObject = new object();
public MessageQueue(int maxQueueSize)
{
MaxQueueSize = maxQueueSize;
unsentMessages = new List<string>();
}
public void AddMessage(string message)
{
lock (lockObject)
{
unsentMessages.Add(message);
}
if (unsentMessages.Count >= MaxQueueSize)
{
SendMessages();
}
}
public void SendMessages()
{
lock (lockObject)
{
var messagesToSend = new List<string>();
while (unsentMessages.Any())
{
// Send messages in batches no larger than 'MaxQueueSize'.
// This allows for dynamic changing of MaxQueueSize, so
// if it changes from Int.Max to 10, we don't try to send
// Int.Max messages to the remote server all at once
messagesToSend = unsentMessages.Take(MaxQueueSize).ToList();
unsentMessages = unsentMessages.Skip(MaxQueueSize).ToList();
// Code to send messages to server goes here:
// RemoteApplication.WebApi.LogMessages(messagesToSend);
Console.WriteLine($"Message Batch (max {MaxQueueSize} messages):");
Console.WriteLine($" - {string.Join($"{Environment.NewLine} - ", messagesToSend)}");
}
}
}
}
如果它有帮助,这是我用来测试它的简单程序:
private static void Main()
{
// Start message queue with setting to NOT send any messages
var messageQueue = new MessageQueue(0);
var cancel = false;
// First thread sends a message once per second
var t1 = new Thread(() =>
{
var counter = 1;
while (true)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
messageQueue.AddMessage($"{DateTime.Now} - First Thread: message #{counter++}");
if (cancel) break;
}
});
// Second thread sends a message once every 2 seconds
var t2 = new Thread(() =>
{
var counter = 1;
while (true)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
messageQueue.AddMessage($"{DateTime.Now} - Second Thread: message #{counter++}");
if (cancel) break;
}
});
t1.Start();
t2.Start();
int secondsToWait = 10;
Console.WriteLine($"nLetting message queue build for {secondsToWait} seconds...");
// A little progress bar while we're waiting...
Console.Write(new string((char)9617, secondsToWait));
Console.SetCursorPosition(0, Console.CursorTop);
while (secondsToWait > 0)
{
secondsToWait--;
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.Write((char)9619);
}
Console.WriteLine();
// Set queue size down to 5
messageQueue.MaxQueueSize = 5;
// Cancel when user presses any key
Console.ReadKey();
cancel = true;
}
请考虑聚合器模式。
您可以根据组中的时间或消息数量定义发送消息组的触发器(以避免流量高时消息繁重(。