C # Implement Asynchronous Message Queue,
C # Asynchronous Message Queue
Message Queue
Message queue is a communication method between processes or between different threads of the same process. The storage column of the software is used to process a series of inputs, usually from the user. The message queue provides an asynchronous communication protocol. The records in each storage column contain detailed information, including the occurrence time, type of the input device, and specific input parameters, that is: the sender and receiver of a message do not need to communicate with the message queue at the same time. The message is stored in the queue until the receiver retrieves it.
Simply put, the queue stores the Command we need to process, but it does not get the processing result in time;
Implementation
In fact, message queues are often stored in the linked list structure. A process with permissions can write or read messages to a message queue.
Currently, many Message queues have many Open-source implementations, including JBoss Messaging, JORAM, Apache ActiveMQ, Sun Open Message Queue, Apache Qpid, and HTTPSQS.
Advantages and disadvantages
The message queue itself is asynchronous. It allows the recipient to retrieve the message after the message is sent for a long time, which is different from most communication protocols. For example, the HTTP protocol used in WWW is synchronous, because the client must wait for the server to respond after sending the request. However, in many cases, we need asynchronous communication protocols. For example, a process notifies another process of an event, but does not need to wait for a response. However, the asynchronous nature of message queues also leads to the disadvantage that the receiver must poll the message queue to receive the most recent message.
Message queues can transmit more information than signals. Compared with pipelines, message queues provide formatted data, which can reduce the workload of developers. However, the size of the message queue is limited.
Read queue messages
There are two main types: (1) server push; (2) Client pull;
Pull: the client regularly polls and takes away messages for processing;
Push: actively notifies subscribers to handle the event subscription;
Message Storage
The simple solution is to store data through a memory linked list. You can also use databases, such as Redis, to persistently store data in local files;
How to Ensure asynchronous processing consistency
Although the main purpose of a queue is to store messages, it also calls and achieves Asynchronization. However, to achieve message consistency, the good way is to differentiate the service processing sequence, such as operating the master-slave DB, writing, and reading, we have no chance to get the desired results from the read database immediately after writing. At the same time, we need to use the intermediate status. When multiple intermediate statuses meet the call results at the same time, they will be processed until the business time, otherwise, the "exception message" will be persistent for the next operation;
Code on
Establish a message opposition core queue
{
Public delegate void messagequeueeventpolicyhandler (Message. BaseMessage message );
Public class MessageQueue: Queue <BaseMessage>
{
Public static MessageQueue GlobalQueue = new MessageQueue ();
Private Timer timer = new Timer ();
Public MessageQueue (){
This. timer. Interval = 5000;
This. timer. Elapsed + = sort y;
This. timer. Enabled = true;
}
Private void Policy (object sender, ElapsedEventArgs e ){
Lock (this ){
If (this. Count> 0 ){
// This. messageNotifyEvent. GetInvocationList () [0]. DynamicInvoke (this. Dequeue ());
Var message = this. Dequeue ();
This. messageNotifyEvent (message );
}
}
}
Private messagequeueeventpolicyhandler messageNotifyEvent;
Public event messagequeueeventpolicyhandler MessageNotifyEvent {
Add {
This. messageNotifyEvent + = value;
}
Remove {
If (this. messageNotifyEvent! = Null ){
This. messageNotifyEvent-= value;
}
}
}
}
}
Event Processing
Public const string OrderCodePrefix = "P ";
Public void Submit (Message. BaseMessage message)
{
Order order = message. Body as Order;
If (order. OrderCode. StartsWith (OrderCodePrefix ))
{
System. Console. WriteLine ("this is a correct order starting with ({0}): {1}", OrderCodePrefix, order. OrderCode );
}
Else {
System. Console. WriteLine ("this is an incorrect order, not starting with ({0}): {1}", OrderCodePrefix, order. OrderCode );
}
}
Personalized Processing Based on specific services;
Append a message to the queue through Proxy
Public class OrderServiceProxy: IOrderService
{
Public void Submit (Message. BaseMessage message)
{
MessageQueue. MessageQueue. GlobalQueue. Enqueue (message );
}
}
Client call
OrderService orderService = new OrderService ();
MessageQueue. MessageQueue. GlobalQueue. MessageNotifyEvent + = orderService. Submit;
Var orders = new List <Order> (){
New Order () {OrderCode = "P001 "},
New Order () {OrderCode = "P002 "},
New Order () {OrderCode = "B003 "}
};
OrderServiceProxy proxy = new OrderServiceProxy ();
Orders. ForEach (order => proxy. Submit (new Message. BaseMessage () {Body = order }));
Console. ReadLine ();
In this way, the event binding and triggering of personalized processing are met, and the message Asynchronization is achieved. We hope that more detailed expansion will be applied to later projects.