当前位置:编程学习 > C#/ASP.NET >>

使用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。 --------------------编程问答--------------------

不懂得代码写简洁一些吗 --------------------编程问答--------------------
引用 3 楼 sp1234 的回复:
你说它能不能做个demo?当然,非常容易。但是基本上你用一台普通的pc做服务器,就只能给自己的7、8个人偶尔通讯的那种demo,用于自娱自乐。

但是你别做测试,特别是别做并发测试。也别做不同浏览器的兼容性和资源(会不会用尽线程资源)测试。

我们要求一个服务器给几千人非常繁忙地使用,例如给地理信息系统使用,给大型企业的缴费系统使用。而不是拿7、8个用户规模的小应用给你做个demo。

现在这个功能做出来以后,是要拿给五、六百人同时使用的,但对于单个用户来说,一天接收到的消息可能屈指可数,客户端类型又不统一,否则直接用双工通信了。Java做HTTP长轮询的应用很方便,难道.net就没有吗。
补充:.NET技术 ,  Web Services
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,