Я делаю свою первую попытку экспериментировать с кометой.Я разработал очень простое веб-приложение для чата - в основном, привет миру комет через c #.Проблема, с которой я сталкиваюсь, заключается в том, что IIS иногда дает сбой, и я имею в виду, что он просто перестает отвечать на запросы HTTP.Затем требуется вечный перезапуск пула приложений, а иногда и всей службы IIS.Я почти уверен, что виновником является объект ManualResetEvent, который я использую для блокировки потоков запросов комет, пока не будет получен сигнал об освобождении (обновлении) этих потоков.Я попытался написать обработчик HTTP, чтобы обойти это, и установить для свойства многоразового использования значение false (для добавления новых потоков запросов в другой экземпляр объекта ManualResetEvent), но это не сработало.Я также пытаюсь реализовать IRegisteredObject, чтобы я мог освободить эти theads, когда приложение закрывается, но это, похоже, тоже не работает.Это все еще падает, и, кажется, нет никакого паттерна, когда он падает (что я заметил).Я почти уверен, что причиной этого является комбинация статических экземпляров и использования 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; }
}
}
Мой класс чата и веб-сервис
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();
}
}
}
Если у кого-то есть хорошая теория о причине и / или исправлении для на первый взглядпроизвольные сбои было бы очень полезно, если бы вы опубликовали:)