我是第一次尝试使用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();
}
}
}
如果有人对原因有一个很好的理论和/或修复看似随意的崩溃,那么如果你发帖,我将非常感激。)