我正在尝试使用Comet进行实验。我开发了一个非常简单的聊天Web应用程序——基本上是通过C#实现Comet的“Hello World”。问题在于,IIS有时会崩溃,我的意思是它停止响应HTTP请求。然后需要很长时间才能重新启动应用程序池,有时甚至整个IIS服务都需要重启。我几乎可以确定罪魁祸首是ManualResetEvent对象,我使用它来阻塞Comet请求线程,直到收到释放(更新)这些线程的信号为止。我试着编写一个HTTP处理程序来解决这个问题,并将可重用属性设置为false(将新的请求线程放置在另一个ManualResetEvent对象的实例中),但这并没有起作用。我还尝试实现IRegisteredObject,以便在应用程序关闭时释放这些线程,但似乎也没有起作用。它仍然会崩溃,而且我没有注意到任何崩溃模式。我几乎可以确定是静态实例和ManualResetEvent的组合导致了这种情况。我只是不确定如何修复它。
Comet.cs(我的简单Comet库)
测试的aspx文件
如果有人对似乎任意崩溃的原因和/或修复方法有好的理论,如果你能发帖分享就非常感激 :)
Comet.cs(我的简单Comet库)
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; }
}
}
我的聊天类和Web服务
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();
}
}
}
如果有人对似乎任意崩溃的原因和/或修复方法有好的理论,如果你能发帖分享就非常感激 :)