MSMQ消息通知系统之消息队列多线程监视器
using System.Messaging;
using System;
using System.Threading;
using System.Transactions;
using System.Collections;
namespace MsmqDemo
{
[Serializable]
class MessageBase
{
/// <summary>
/// 消息类型
/// </summary>
private
string messagetype;
public string MessageType
{
get
{ return messagetype; }
set
{ messagetype = value; }
}
/// <summary>
/// 消息内容
/// </summary>
private
string messagebody;
public string MessageBody
{
get
{ return messagebody; }
set
{ messagebody = value; }
}
}
class MsgRecorder:IDisposable
{
protected
static readonly
string path=@"FormatName:DIRECT=OS:.\Private$\MessageQueue";
protected
MessageQueueTransactionType type = MessageQueueTransactionType.Automatic;
protected
TimeSpan timeout;//
= TimeSpan.FromSeconds(10d);
protected
MessageQueue queue;
public
MsgRecorder(int _timeout)
{
this.timeout
= TimeSpan.FromSeconds(Convert.ToDouble(_timeout));
queue = new
MessageQueue(path);
//
Performance optimization since we don't need these features
queue.DefaultPropertiesToSend.AttachSenderId
= false;
queue.DefaultPropertiesToSend.UseAuthentication = false;
queue.DefaultPropertiesToSend.UseEncryption = false;
queue.DefaultPropertiesToSend.AcknowledgeType = AcknowledgeTypes.None;
queue.DefaultPropertiesToSend.UseJournalQueue = false;
}
public virtual Message
Receive()
{
try
{
using
(Message msg = queue.Receive(timeout, type))
return
msg;
}
catch
{
throw;
}
}
#region IDisposable 成员
public void Dispose()
{
queue.Dispose();
}
#endregion
}
class Program
{
private
static readonly
int threadCount = 2;
private
static readonly
int batchSize = 10;
private
static readonly
int transactionTimeout = 10;
private
static readonly
int queueTimeout = 10;
private
static int
totalOrdersProcessed = 0;
static void
{
Thread
workticketThread;
Thread[]
threads = new Thread[threadCount];
for
(int i = 0; i < threadCount; i++)
{
workticketThread = new Thread(new ThreadStart(ProcessData));
workticketThread.IsBackground =
true;
//STA
Thread 将创建并进入一个单线程单元。
//MTA
Thread 将创建并进入一个多线程单元。
//Unknown
尚未设置ApartmentState 属性。
workticketThread.SetApartmentState(ApartmentState.STA);
workticketThread.Start();
threads[i] = workticketThread;
}
Console.WriteLine("Processing started. Press Enter to stop.");
Console.ReadLine();
Console.WriteLine("Aborting Threads. Press wait...");
//abort
all threads
foreach
(Thread t in
threads)
{
t.Abort();
}
Console.WriteLine("Process compeltely");
}
private
static void
ProcessData()
{
// the
transaction timeout should be long enough to handle all of orders in the batch
TimeSpan
tsTimeout = TimeSpan.FromSeconds(Convert.ToDouble(transactionTimeout * batchSize));
while
(true)
{
TimeSpan
datatimeStarting =new TimeSpan(
DateTime.Now.Ticks);
double
elapsedTime = 0;
int
processedItems = 0;
ArrayList
queueOrders = new ArrayList();
#region scope
using
(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, tsTimeout))
{
using (MsgRecorder recorder = new MsgRecorder(queueTimeout))
{
for (int j = 0; j
< batchSize; j++)
{
try
{
if
((elapsedTime + queueTimeout + transactionTimeout) < tsTimeout.TotalSeconds)
{
//message list
queueOrders.Add(recorder.Receive());
}
else
{
//timeout
j =
batchSize; //
exit loop
}
//update elapsed time
elapsedTime
= new TimeSpan(DateTime.Now.Ticks).TotalSeconds -
datatimeStarting.TotalSeconds;
}
catch
(TimeoutException)
{
//exit loop because no more messages are waiting
j =
batchSize;
}
catch (Exception)
{
j =
batchSize;
Console.WriteLine("已经没有数据,线程进入休眠~~~~~~~~~~~~~。。~");
System.Threading.Thread.Sleep(60
* 1000);
}
}
//process the queued orders
for (int k = 0; k
< queueOrders.Count; k++)
{
//process
Console.WriteLine("process
one");
processedItems++;
totalOrdersProcessed++;
}
//batch complete or MSMQ receive timed out
scope.Complete();
}
Console.WriteLine("(Thread Id
" + Thread.CurrentThread.ManagedThreadId
+ ") batch finished, " +
processedItems + " items, in " +
elapsedTime.ToString() + " seconds. Now:"+DateTime.Now.ToShortTimeString());
}
#endregion
}
}
}
}