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
}
}
}
}