很多需要提高应用性能(提高立即响应速度(但不立即处理)、提高吞吐能力、提升用户体验)的场景,
都采用异步处理的机制,.Net 中可能用 MSMQ 的实现样例不少,其实自行实现异步队列并不复杂。
最近有两个项目组的同事向我要了类似的关于实现异步队列的方法,于是翻出了两年以前写的实现 SP 与运营商短信网关通信的上下行短信队列处理相关的代码,尽管不难,自觉多少有点儿技术含量,拿出来晒晒,因此去掉了所有的与业务相关的逻辑,保留通用的异步处理功能,提炼出一套完整的、通用的、核心关键代码,编译后即可运行,方便大家。
该 Remoting 异步队列的实现,主要使用的 .Net 技术是多线程、Remoting、泛型容器类...
流程如下
1.并发若干客户端程序通过调用 RemotingQueue Server 提供的公开远程方法 Enqueue 将数据元素入队尾
2.RemotingQueue Server 发现队列不为空,则并发若干(n)多线程陆续 Dequeue 队首数据元素并处理
注意:
1.队列的数据元素定义需自行实现
br
很多需要提高应用性能(提高立即响应速度(但不立即处理)、提高吞吐能力、提升用户体验)的场景,
都采用异步处理的机制,.Net 中可能用 MSMQ 的实现样例不少,其实自行实现异步队列并不复杂。
最近有两个项目组的同事向我要了类似的关于实现异步队列的方法,
于是翻出了两年以前写的实现 SP 与运营商短信网关通信的上下行短信队列处理相关的代码,
尽管不难,自觉多少有点儿技术含量,拿出来晒晒,
因此去掉了所有的与业务相关的逻辑,保留通用的异步处理功能,
提炼出一套完整的、通用的、核心关键代码,编译后即可运行,方便大家。
该 Remoting 异步队列的实现,主要使用的 .Net 技术是多线程、Remoting、泛型容器类...
流程如下
1.并发若干客户端程序通过调用 RemotingQueue Server 提供的公开远程方法 Enqueue 将数据元素入队尾
2.RemotingQueue Server 发现队列不为空,则并发若干(<n)多线程陆续 Dequeue 队首数据元素并处理
注意:
1.队列的数据元素定义需自行实现
2.对出列数据元素的处理程序需自行实现
本人手懒,就写这么多,不再多写废话!
完整代码如下,注释不多,手懒,请谅解!
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//*
Remoting 异步队列实现,流程如下
1.并发若干客户端程序通过调用 RemotingQueue Server 提供的公开远程方法 Enqueue 将数据元素入队尾
2.RemotingQueue Server 发现队列不为空,则并发若干线程陆续 Dequeue 队首数据元素并处理
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
注意:
1.队列的数据元素定义需自行实现
2.对出列数据元素的处理程序需自行实现
*/
// server.cs
//C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe server.cs /r:share.dll
//.Net 2.0 Remoting 宿主程序 服务 + Console
namespace Microshaoft.RemotingObjects.Server
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
using System;
using System.Threading;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Serialization.Formatters;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using System.ServiceProcess;
using System.ComponentModel;
using System.Configuration.Install;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using Microshaoft.RemotingObjects.Share;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public class RemotingQueueServiceHost : ServiceBase
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 应用程序的主入口点。
/// </summary>
//[STAThread]
static void Main(string[] args)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//Microshaoft
//Microshaoft TODO: 在此处添加代码以启动应用程序
//Microshaoft
RemotingQueueServiceHost service = new RemotingQueueServiceHost();
if (args != null)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("Console");
service.OnStart(null);
Console.ReadLine();
return;
}
Console.WriteLine("Service");
ServiceBase.Run(service);
}
protected override void OnStart(string[] args)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine(Environment.Version.ToString());
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = TypeFilterLevel.Full;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
IDictionary props = new Hashtable();
props["port"] = 8080;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
TcpChannel tc = new TcpChannel(props, null, provider);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
ChannelServices.RegisterChannel(tc, false);
RemotingConfiguration.RegisterWellKnownServiceType
(
typeof(RemotingQueue)
, "queueurl"
, WellKnownObjectMode.Singleton
);
RemotingQueue.OnDequeue += new RemotingQueue.QueueEventHandler(DequeueProcess);
Console.WriteLine("Server . , Press Enter key to exit.");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public static void DequeueProcess(Item item)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//Microshaoft TO DO
//Microshaoft 队列的数据元素定义需自行实现
//Microshaoft 数据库访问
//Microshaoft 发邮件等
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
DateTime DequeueTime = DateTime.Now;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//Microshaoft Thread.Sleep(100); //Microshaoft 模拟长时间任务
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
DateTime EndTime = DateTime.Now;
Console.WriteLine
(
"QueueRemainCount {0}, Enqueue {1}, Dequeue {2},[{3}], End {4},[{5}],[{6}]"
, RemotingQueue.Count
, item.EnqueueTime
, DequeueTime
, (DequeueTime.Ticks - item.EnqueueTime.Ticks)/10000
, EndTime
, (EndTime.Ticks - DequeueTime.Ticks)/10000
, RemotingQueue.ConcurrentThreadsCount
);
}
}
[RunInstallerAttribute(true)]
public class ProjectInstaller: Installer
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private ServiceInstaller serviceInstaller;
private ServiceProcessInstaller processInstaller;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public ProjectInstaller()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
processInstaller = new ServiceProcessInstaller();
serviceInstaller = new ServiceInstaller();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//Microshaoft Service will run under system account
processInstaller.Account = ServiceAccount.LocalSystem;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//Microshaoft Service will have Start Type of Manual
serviceInstaller.StartType = ServiceStartMode.Manual;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
serviceInstaller.ServiceName = "RemotingQueueService";
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Installers.Add(serviceInstaller);
Installers.Add(processInstaller);
}
}
}
//Microshaoft =====================
//Microshaoft Remoting Server Object
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
namespace Microshaoft.RemotingObjects
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using System.Threading;
using System.Configuration;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using System.Collections.Generic;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using Microshaoft.RemotingObjects.Share;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public class RemotingQueue : MarshalByRefObject
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
public delegate void QueueEventHandler(Item item);
public static event QueueEventHandler OnDequeue;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private static Queue<Item> _Queue = new Queue<Item>();
private static object _SyncLockObject = new object();
private static int _MaxConcurrentThreadsCount = 10; //Microshaoft 允许并发出列处理线程数为 10
private static int _ConcurrentThreadsCount = 0; //Microshaoft 用于控制并发线程数
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private static bool _QueueRuning = false;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//Microshaoft 服务启动后可立即开启新的线程调用此方法(死循环)
private static void QueueRun() //Microshaoft ThreadStart
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (!_QueueRuning)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_QueueRuning = true;
lock (_SyncLockObject)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
ThreadStart ts = new ThreadStart(QueueRunThreadProcess);
Thread t = new Thread(ts);
t.Name = "QueueRunThreadProcess";
t.Start();
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public static int Count
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return _Queue.Count;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public static int ConcurrentThreadsCount
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return _ConcurrentThreadsCount;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private static void QueueRunThreadProcess()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("Queue Runing ");
while (_Queue.Count > 0) //Microshaoft 死循环
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Item item = null;
lock(_SyncLockObject)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_ConcurrentThreadsCount < _MaxConcurrentThreadsCount)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_Queue.Count > 0)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//_ConcurrentThreadsCount ++;
Interlocked.Increment(ref _ConcurrentThreadsCount);
item = _Queue.Dequeue();
}
}
}
if (item != null)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//Microshaoft ThreadPool.QueueUserWorkItem(new WaitCallback(OnDequeueThreadProcess), item);
ThreadProcessState tps = new ThreadProcessState();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
tps.Item = item;
Thread t = new Thread(new ThreadStart(tps.ThreadProcess));
t.Name = string.Format("ConcurrentThread[{0}]", _ConcurrentThreadsCount);
t.Start();
}
}
_QueueRuning = false;
Console.WriteLine("Queue Running Stopped ");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void Enqueue(Item item)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//Microshaoft 队列的数据元素定义需自行实现 Item
item.EnqueueTime = DateTime.Now;
_Queue.Enqueue(item);
//Microshaoft Console.WriteLine("Enqueue {0}", item.Name);
if (!_QueueRuning)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
QueueRun();
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private static void OnDequeueThreadProcess(Item item)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
try
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (OnDequeue != null)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
OnDequeue(item);
}
DequeueThreadProcess();
}
catch (Exception ex)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine(ex.Message);
}
finally
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// lock (_SyncLockObject)
/// {
//Microshaoft Console.WriteLine("工作线程数: {0}", _ConcurrentThreadsCount - 1);
//_ConcurrentThreadsCount --;
Interlocked.Decrement(ref _ConcurrentThreadsCount);
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// }
}
}
static int count = 0;
private static void DequeueThreadProcess()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
while (_Queue.Count > 0)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Item item = null;
lock (_SyncLockObject)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_Queue.Count > 0)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
item = _Queue.Dequeue();
//count ++;
Interlocked.Increment(ref count);
//Microshaoft Console.WriteLine("Queue Count: {0},count: {1}", _Queue.Count, count);
}
}
if (item != null)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (OnDequeue != null)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
OnDequeue(item);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private class ThreadProcessState
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private Item _item;
public Item Item
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return _item;
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_item = value;
}
}
public void ThreadProcess()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//Microshaoft Console.WriteLine("{0} Thread Start:", Thread.CurrentThread.Name);
RemotingQueue.OnDequeueThreadProcess(_item);
//Microshaoft Console.WriteLine("{0} Thread End!", Thread.CurrentThread.Name);
if (RemotingQueue._ConcurrentThreadsCount == 0)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine("All Threads Finished! Queue Count {0}", RemotingQueue.Count);
}
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
// share.cs
//Server、Client 均需引用此 share.dll
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe /t:library share.cs
//TO DO
//队列的数据元素定义需自行实现,示例如下:
namespace Microshaoft.RemotingObjects.Share
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
using System;
[Serializable]
public class Item
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private string _Name;
public string Name
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return _Name;
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_Name = value;
}
}
private DateTime _EnqueueTime;
public DateTime EnqueueTime
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return _EnqueueTime;
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_EnqueueTime = value;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
// client.cs
//C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\csc.exe client.cs /r:share.dll
namespace Microshaoft.RemotingObjects.Client
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
using System;
using System.Collections;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Serialization.Formatters;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using System.Threading;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
using Microshaoft.RemotingObjects;
using Microshaoft.RemotingObjects.Share;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public class Class1
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
static RemotingQueue _queue;
public static void Main()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Console.WriteLine(Environment.Version.ToString());
Class1 a = new Class1();
a.Run();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void Run()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_queue = (RemotingQueue) Activator.GetObject
(
typeof(RemotingQueue)
, "tcp://127.0.0.1:8080/queueUrl"
);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//Microshaoft 以下是耗时的主程序
for (int i = 0; i < 100; i++)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Thread x = new Thread(new ThreadStart(ThreadProcess));
x.Start();
}
}
public void ThreadProcess()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for (int i = 0; i < 100; i++)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Item x = new Item();
DateTime EnqueueTime = DateTime.Now;
x.Name = EnqueueTime.ToString();
_queue.Enqueue(x);
Console.WriteLine
(
"Enqueue: {0},[{1}]"
, EnqueueTime
, (DateTime.Now.Ticks - EnqueueTime.Ticks)/10000
);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
}
//Microshaoft =========================================
//Microshaoft Remoting Object Client Local Proxy
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
namespace Microshaoft.RemotingObjects
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
using System;
using Microshaoft.RemotingObjects.Share;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public interface RemotingQueue
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
void Enqueue(Item item);
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)