c#comet服务器冻结IIS

时间:2011-06-20 04:08:08

标签: c# .net iis comet

我是第一次尝试使用Comet进行实验。我开发了一个非常简单的聊天网络应用程序 - 基本上是通过c#的彗星问候世界。我遇到的问题是IIS有时会崩溃,崩溃我的意思是它只是停止响应HTTP请求。然后,它需要重新启动应用程序池,有时甚至是整个IIS服务。我几乎肯定是罪魁祸首是我用来阻止彗星请求线程的ManualResetEvent对象,直到收到释放(更新)这些线程的信号。我尝试编写一个HTTP处理程序来解决这个问题并将可重用属性设置为false(将新请求线程放在另一个ManualResetEvent对象实例上),但这不起作用。我也在尝试实现IRegisteredObject,这样我就可以在应用程序关闭时释放那些theads,但这似乎也不起作用。它仍然崩溃,并且它崩溃时似乎没有任何模式(我已经注意到了)。我几乎可以肯定它是静态实例的组合以及导致它的ManualResetEvent的使用。我只是不确定如何或如何解决这个问题。

Comet.cs(我的简单彗星lib)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Mail;
using System.Web.Hosting;

namespace Comet
{
    public class CometCore : IRegisteredObject
    {
        #region Globals
        private static CometCore m_instance = null;
        private List<CometRequest> m_requests = new List<CometRequest>();
        private int m_timeout = 120000; //Default - 20 minutes;
        #endregion

        #region Constructor(s)
        public CometCore()
        {
            HostingEnvironment.RegisterObject(this);
        }
        #endregion

        #region Properties
        /// <summary>
        /// Singleton instance of the class
        /// </summary>
        public static CometCore Instance
        {
            get
            {
                if (m_instance == null)
                    m_instance = new CometCore();
                return m_instance;
            }
        }

        /// <summary>
        /// In milliseconds or -1 for no timeout.
        /// </summary>
        public int Timeout { get { return m_timeout; } set { m_timeout = value; } }
        #endregion

        #region Public Methods
        /// <summary>
        /// Pauses the thread until an update command with the same id is sent.
        /// </summary>
        /// <param name="id"></param>
        public void WaitForUpdates(string id)
        {
            //Add this request (and thread) to the list and then make it wait.
            CometRequest request;
            m_requests.Add(request = new CometRequest(id));

            if (m_timeout > -1)
                request.MRE.WaitOne(m_timeout);
            else
                request.MRE.WaitOne();
        }

        /// <summary>
        /// Un-pauses the threads with this id.
        /// </summary>
        /// <param name="id"></param>
        public void SendUpdate(string id)
        {
            for (int i = 0; i < m_requests.Count; i++)
            {
                if (m_requests[i].ID.Equals(id))
                {
                    m_requests[i].MRE.Set();
                    m_requests.RemoveAt(i);
                    i--;
                }
            }
        }
        #endregion

        public void Stop(bool immediate)
        {
            //release all threads
            for (int i = 0; i < m_requests.Count; i++)
            {
                m_requests[i].MRE.Set();
                m_requests.RemoveAt(i);
                i--;
            }
        }
    }

    public class CometRequest
    {
        public string ID = null;
        public ManualResetEvent MRE = new ManualResetEvent(false);
        public CometRequest(string pID) { ID = pID; }
    }
}

我的聊天课程和网络服务

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using Comet;

namespace CometTest
{
    /// <summary>
    /// Summary description for Chat
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [System.Web.Script.Services.ScriptService]
    public class Chat : System.Web.Services.WebService
    {

        [WebMethod]
        public string ReceiveChat()
        {
            return ChatData.Instance.GetLines();
        }

        [WebMethod]
        public string ReceiveChat_Comet()
        {
            CometCore.Instance.WaitForUpdates("chat");
            return ChatData.Instance.GetLines();
        }

        [WebMethod]
        public void Send(string line)
        {
            ChatData.Instance.Add(line);
            CometCore.Instance.SendUpdate("chat");
        }
    }

    public class ChatData
    {
        private static ChatData m_instance = null;
        private List<string> m_chatLines = new List<string>();
        private const int m_maxLines = 5;

        public static ChatData Instance
        {
            get
            {
                if (m_instance == null)
                    m_instance = new ChatData();
                return m_instance;
            }
        }

        public string GetLines()
        {
            string ret = string.Empty;
            for (int i = 0; i < m_chatLines.Count; i++)
            {
                ret += m_chatLines[i] + "<br>";
            }
            return ret;
        }

        public void Add(string line)
        {
            m_chatLines.Insert(0, line);
            if (m_chatLines.Count > m_maxLines)
            {
                m_chatLines.RemoveAt(m_chatLines.Count - 1);
            }
        }
    }
}

测试aspx文件

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CometTest.Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">

        <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Services>
                <asp:ServiceReference Path="~/Chat.asmx" />
            </Services>
        </asp:ScriptManager>

        <div id="lyrChatLines" style="height: 200px; width: 300px; border: 1px solid #cccccc; overflow: scroll">
        </div>

        <asp:Panel runat="server" DefaultButton="cmdSend">
            <asp:UpdatePanel runat="server">
                <ContentTemplate>
                    <asp:TextBox style="width: 220px" runat="server" ID="txtChat"></asp:TextBox>
                    <asp:Button runat="server" ID="cmdSend" Text="Send" OnClick="cmdSend_Click" />
                </ContentTemplate>
            </asp:UpdatePanel>
        </asp:Panel>

        <script type="text/javascript">

            function CometReceive()
            {
                CometTest.Chat.ReceiveChat_Comet(receive, commError, commError);
            }

            function ReceiveNow()
            {
                CometTest.Chat.ReceiveChat(receive, commError, commError);
            }

            function receive(str)
            {
                document.getElementById("lyrChatLines").innerHTML = str;
                setTimeout("CometReceive()", 0);
            }

            function commError()
            {
                document.getElementById("lyrChatLines").innerHTML =
                    "Communication Error...";
                setTimeout("CometReceive()", 5000);
            }

            setTimeout("ReceiveNow()", 0);
        </script>
    </form>
</body>
</html>

背后的aspx代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace CometTest
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void cmdSend_Click(object sender, EventArgs e)
        {
            Chat service = new Chat();
            service.Send
            (
                Request.UserHostAddress + "> " +
                txtChat.Text
            );
            txtChat.Text = string.Empty;
            txtChat.Focus();
        }
    }
}

如果有人对原因有一个很好的理论和/或修复看似随意的崩溃,那么如果你发帖,我将非常感激。)

1 个答案:

答案 0 :(得分:1)

此问题.NET Comet engine有一些链接应该指向正确的方向。您需要查看实现IHttpAsyncHandler来处理长时间运行的彗星请求。