时间:2019-05-17 标签:c#cometserverfreezeIIS
我正在第一次尝试彗星实验。我开发了一个非常简单的聊天 Web 应用程序 - 基本上是通过 C# 实现的 Comet 的 hello world。我遇到的问题是 IIS 有时会崩溃,我所说的崩溃是指它只是停止响应 HTTP 请求。然后需要永远重新启动应用程序池,有时甚至整个 IIS 服务。我几乎肯定罪魁祸首是我用来阻止 comet 请求线程的 ManualResetEvent 对象,直到收到释放(更新)这些线程的信号。我尝试编写一个 HTTP 处理程序来解决此问题,并将可重用属性设置为 false(将新请求线程放在 ManualResetEvent 对象的另一个实例上),但这不起作用。我还尝试实现 IRegisteredObject,这样我就可以在应用程序关闭时释放这些 thead,但这似乎也不起作用。它仍然崩溃,并且崩溃时似乎没有任何模式(我注意到)。我几乎可以肯定这是静态实例和使用 ManualResetEvent 的组合导致的。我只是不确定如何或如何解决这个问题。
Comet.cs(我的简单彗星库)
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();
}
}
}
如果有人对看似随意的崩溃的原因和/或修复有一个很好的理论,如果您' ld帖子:)
I'm making my first attempt at experimenting with Comet. I developed a very simple chat web app - basically a hello world of comet via c#. The problem i'm having is IIS will sometimes crash and by crash i mean it simply stops responding to HTTP requests. It then takes for ever to restart the app pool and sometimes the whole IIS service. I'm almost positive the culprit is the ManualResetEvent object I'm using to block comet requests threads until a signal to release (update) those threads is received. I tried writing an HTTP handler to get around this and set the reusable property to false (to put new requests threads on another instance of the ManualResetEvent object) but that didn't work. I'm also trying implementing the IRegisteredObject so I can release those theads when the app is shutting down but that doesn't seem to work either. It still crashes and there doesn't seem to be any pattern in when it crashes (that i've noticed). I'm almost sure it's a combination of static instances and the use of ManualResetEvent that's causing it. I just don't know for sure how or how to fix it for that matter.
Comet.cs (My simple comet 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; }
}
}
My chat class and web service
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);
}
}
}
}
The test aspx file
<%@ 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>
And the aspx code behind
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();
}
}
}
If anyone has a good theory on the cause and/or fix for the seemingly arbitrary crashes it would be much appreciated if you'ld post :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个问题.NET Comet引擎有一些链接应该为您指明正确的方向。您需要考虑实现 IHttpAsyncHandler 来处理长时间运行的 comet 请求。
This question .NET Comet engine has some links that should point you in the right direction. You need to look at implementing a IHttpAsyncHandler to handle the long running comet request.