先談談需求吧
最近一個Case
需求如下圖
有了發布者還需要訂閱者
public class Admin
{
/**//// <summary>
/// 用這個保存所有收到的數據
/// </summary>
public IList<string> MessageList
{ get; set; }
public Admin(Monitor monitor)
{
MessageList = new List<string>();
monitor
}
[img]_
private void ReciveMessage(object sender
[img]_
MessageList
[img]_
}
[img]_
}
[img]_
Ok
分析
第一個問題
在上面的Monitor的實現中添加下面的代碼
[img]_
private static Monitor _instance = null;
[img]_
Monitor Current
[img]_
get
[img]_
[img]_
if (_instance == null)
[img]_
_instance = new Monitor();
[img]_
return _instance;
[img]_
}
[img]_
但是本系統存在多個客戶端
[img]_
public static Monitor Current
[img]_
[img]_
get
[img]_
[img]_
object o = new object();
[img]_
if (_instance == null)
[img]_
[img]_
lock (o)
[img]_
[img]_
if (_instance == null)
[img]_
_instance = new Monitor();
[img]_
}
[img]_
}
[img]_
return _instance;
[img]_
}
[img]_
}
[img]_
(PS:為什麼使用單件就可以跨請求保存實例了呢?因為這裡使用了一個static member保存Monitor的引用
第二個問題
在管理頁面上我放置一個
[img]_
Admin admin = context
[img]_
if(admin == null)
[img]_
admin = new Admin(Monitor
[img]_
context
[img]_
[img]_
注意
在管理頁面還有個一個SetInterval不斷的調用一個含有ajax的方法
[img]_
public void ProcessRequest(HttpContext context)
[img]_
context
[img]_
context
[img]_
context
[img]_
context
[img]_
Admin admin = context
[img]_
if (admin == null || admin
admin
[img]_
return;
[img]_
string[] messages = new string[admin
[img]_
admin
[img]_
StringBuilder sb = new StringBuilder();
[img]_
for (int i =
[img]_
[img]_
sb
[img]_
}
[img]_
admin
[img]_
context
[img]_
context
[img]_
context
[img]_
[img]_
OK
還查看了一些關於長連接的文章
完整的代碼稍後提供
寫完這個Post後本來想把完整代碼實現傳上來
首先我進一步談一下需求
這是一個Web Application
由於數據提交非常頻繁
下面我將以我當初思考的思路為主線描述
第一個版本
//在程序裡我寫了一個靜態類
相當於原來的//Application對象
public static ApplicationData
{
//這個隊列用來保存客戶端傳遞過來的數據
public static Queue<DataHead> OperateDataList = new Queue<DataHead>();
//這個List也是保存客戶端傳遞過來的數據的
//當一個監視頁面的請求到來的時候將這個List的數據Response過去
public static IList<DataHead> MonitorDataList = new List<DataHead>();
}
public class ReciveDataHandler : IHttpHandler
{
//……
Public void ProcessRequest(HttpContext context)
{
//解析從客戶端傳遞過來的數據
DataHead data = GetData(context);
OperateDataList
If(OperateDataList
{
//將數據寫入到數據庫
AddToBase();
}
MonitorDataList
}
}
//監視頁面從這裡獲取數據
public class MonitorHandler : IHttpHandler
{
//……
Public void ProcessRequest(HttpContext context)
{
If(MonitorDataList
{
//將MonitorDataList裡的數據Response出去
OutPut();
MonitorDataList
}
}
}
說實話
怎麼辦?再一看這不是事件訂閱所描述的場景麼?所以就有了上一篇Post的Solution
Public class ReciveData : IHttpHandler
{
//………
//將客戶端傳遞過來的數據存入數據庫
}
Public class MonitorHandler : IHttpHandler
{
//………
//為null的時候說明該管理員第一次監視
If(Session[
{
//根據時間從服務器取出數據
//並將取出數據的最後一個id保存在session中
Session[
}
//不為null則說明該管理員已經開始監視了
Else
{
//根據session裡保存的最後一個id
Session[
}
}
看似這個方案不錯
經過一番思考後我還是回到我自己的Solution上
[img]_
public class DataEventArgs : EventArgs
[img]_
public string Message
[img]_
[img][/img]{get;set;}
[img]_
public DataEventArgs(string message)
[img]_
[img]_
this
[img]_
}
[img]_
}
[img]_
public class Monitor
[img]_
[img][/img]{
[img]_
public event EventHandler<DataEventArgs> DataIn;
[img]_
private void SendData(string message)
[img]_
[img]_
if (DataIn != null)
[img]_
[img]_
DataEventArgs e = new DataEventArgs(message);
[img]_
DataIn(this
[img]_
}
[img]_
}
[img]_
/**//// <summary>
[img]_
/// 這個方法被一個HttpHandler調用
[img]_
/// 數據處理後作為字符串傳遞給該方法
[img]_
/// </summary>
[img]_
/// <param name=
[img]_
public void ReciveData(string message)
[img]_
[img]_
SendData(message);
[img]_
}
[img]_
[img]_
From:http://tw.wingwit.com/Article/program/net/201311/13325.html