使用WCF实现长轮询
因为项目需求,现要求安卓和.net两种客户端都可以以长轮询的方式请求资源。具体是以长轮询的方式来模拟消息推送。目前又因为要求服务端使用WCF,客户端以异步方式调用服务,发送请求之后,服务端该如何Hold住此请求?我想到的是挂起服务线程,直到有对应消息时再唤醒此服务线程,但在测试多并发时总是出现IIS崩溃的情况。有知道原因的不?或者是否有更好服务端实现方式。下面贴出关键代码。
[ServiceBehavior(ConcurrencyMode= ConcurrencyMode.Multiple)]
public class Service1 : IService1
{
public IAsyncResult BeginGetData(string msg, AsyncCallback callback, object state)
{
var async = new CompletedAsyncResult<string>(msg, callback, state);
var t = System.Threading.Thread.CurrentThread;
AsyncThread at = new AsyncThread(t,async,1);
lock (MsgManager.Instance.Threads)
{
if (MsgManager.Instance.Threads.Keys.Contains(msg))
{
var thread = MsgManager.Instance.Threads[msg];
try
{
thread.MyThread.Abort();
}
catch { }
MsgManager.Instance.Threads[msg] = at;
}
else
MsgManager.Instance.Threads.Add(msg, at);
}
t.Suspend();
return async;//return 之后自动会执行callback
}
public string EndGetData(IAsyncResult result)
{
var r = result as CompletedAsyncResult<string>;
return r.User+ "'s Msg :"+r.Data+"\t"+DateTime.Now.ToString()+"\n"+"Async is completed.\n";
}
}
AsyncThread是我自己写的封装线程和返回值的类,CompletedAsyncResult<T>是实现IAsyncResult的类,用于寄存用户和消息 ,MsgManager为消息管理器
public class MsgManager
{
public List<MsgInfo> MsgList { get { return msgList; } }
private List<MsgInfo> msgList;
private Dictionary<string, AsyncThread> threadsList;
public Dictionary<string, AsyncThread> Threads { get { return threadsList; } }
private MsgManager()
{
msgList = new List<MsgInfo>();
threadsList = new Dictionary<string, AsyncThread>();
beginTimer();
}
private void beginTimer()
{
System.Timers.Timer timer = new System.Timers.Timer(3000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (this)
{
List<string> keyList = new List<string>();
foreach (var d in threadsList)
{
MsgInfo msg = null;
foreach (var m in msgList)
{
if (m.UserName == d.Key)
{
msg = m;
msgList.Remove(m);
break;
}
}
if (msg != null)
{
keyList.Add(d.Key);
d.Value.Async.Data = msg.Msg;
d.Value.Async.User = d.Key;
d.Value.MyThread.Resume();
}
}
foreach (string key in keyList)
{
threadsList.Remove(key);
}
}
}
private static MsgManager instance;
public static MsgManager Instance
{
get
{
if (instance == null)
instance = new MsgManager();
return instance;
}
}
public MsgInfo GetMsgByName(string name)
{
MsgInfo info= null;
msgList.ForEach(msg =>
{
if (msg.UserName == name)
info = msg;
});
return info;
}
}
timer_Elapsed方法即为取得消息并唤醒相关线程的方法。
这课题拖了好久了,网上也找不到类似的解决方案,恼…… --------------------编程问答-------------------- 不懂帮顶 --------------------编程问答-------------------- 课题?
现在这个时代,时髦的名词未必代表着真实靠谱的产品,就算是别人做出了满汉全席你也未必能够做这个“课题”。
我给出的忠告是:web长连接在目前的“浏览器-web服务器”架构下还是一个伪技术。 --------------------编程问答-------------------- 你说它能不能做个demo?当然,非常容易。但是基本上你用一台普通的pc做服务器,就只能给自己的7、8个人偶尔通讯的那种demo,用于自娱自乐。
但是你别做测试,特别是别做并发测试。也别做不同浏览器的兼容性和资源(会不会用尽线程资源)测试。
我们要求一个服务器给几千人非常繁忙地使用,例如给地理信息系统使用,给大型企业的缴费系统使用。而不是拿7、8个用户规模的小应用给你做个demo。 --------------------编程问答--------------------
不懂得代码写简洁一些吗 --------------------编程问答--------------------
现在这个功能做出来以后,是要拿给五、六百人同时使用的,但对于单个用户来说,一天接收到的消息可能屈指可数,客户端类型又不统一,否则直接用双工通信了。Java做HTTP长轮询的应用很方便,难道.net就没有吗。
补充:.NET技术 , Web Services