using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace TestApplication
{
/// <summary>
/// 消息队列
/// </summary>
/// <typeparam name="T"></typeparam>
public class MessageQueue<T>
{
private static object _lockObj = new object();
private static MessageQueue<T> _instance;
private Queue<T> _msgQueue;
private MessageQueue()
{
this._msgQueue = new Queue<T>();
}
public static MessageQueue<T> CreateInstance()
{
if (_instance == null)
{
lock (_lockObj)
{
if (_instance == null)
{
_instance = new MessageQueue<T>();
}
}
}
return _instance;
}
public void PushMessage(T message)
{
lock (_lockObj)
{
if (_msgQueue.Contains(message))
return;
_msgQueue.Enqueue(message);
}
}
public bool IsEmpty()
{
return _msgQueue.Count < 1;
}
public T GetMessage()
{
lock (_lockObj)
{
if (_msgQueue.Count > 0)
return _msgQueue.Dequeue();
else
return default(T);
}
}
}
public class MessagePump<T>
{
public Action<T> DoAction;
private static object _lockObj = new object();
private static MessagePump<T> _instance;
public static MessagePump<T> CreateInstance()
{
if (_instance == null)
{
lock (_lockObj)
{
if (_instance == null)
{
_instance = new MessagePump<T>();
}
}
}
return _instance;
}
public MessageQueue<T> Messages { get; set; }
public bool IsWorking { get; private set; }
public void DoWork()
{
T empty = default(T);
while (!Messages.IsEmpty())
{
IsWorking = true;
var item = Messages.GetMessage();
if (item.Equals(empty))
{
break;
}
if (DoAction != null)
DoAction(item);
}
IsWorking = false;
}
}
}
调用
private void button1_Click(object sender, EventArgs e)
{
MessageQueue<int> messages = MessageQueue<int>.CreateInstance();
MessagePump<int> pump = MessagePump<int>.CreateInstance();
pump.Messages = messages;
pump.DoAction = new Action<int>((item) =>
{
this.Invoke(new Action(() =>
{
listBox1.Items.Add(item);
}));
// 模拟处理失败,重新入队
if (item % 2 == 0)
{
messages.PushMessage(item + 1);
if (!pump.IsWorking)
pump.DoWork();
}
}
);
List<Thread> threads = new List<Thread>();
for (var i = 1; i <= 10; i++)
{
int j = i;
threads.Add(new Thread(() =>
{
messages.PushMessage(j);
if (!pump.IsWorking)
pump.DoWork();
}));
}
for(var i = 0; i < threads.Count; i++)
{
threads[i].Start();
}
}