2011-06-20 10 views
5

Podejmuję pierwszą próbę eksperymentowania z kometą. Stworzyłem bardzo prostą aplikację internetową na czacie - w zasadzie cześć świata komety za pośrednictwem C#. Problem, który mam, polega na tym, że usługi IIS czasami się zawieszają, co oznacza, że ​​po prostu przestaje odpowiadać na żądania HTTP. Ponowne uruchomienie puli aplikacji i czasami całej usługi IIS trwa zawsze. Jestem prawie pewien, że winowajcą jest obiekt ManualResetEvent, którego używam do blokowania wątków żądań komet aż do otrzymania sygnału do wydania (aktualizacji) tych wątków. Próbowałem napisać procedurę obsługi HTTP, aby obejść to i ustawić właściwość do ponownego użycia na false (aby umieścić nowe żądania wątków na innym wystąpieniu obiektu ManualResetEvent), ale to nie zadziałało. Próbuję również wdrażać IRegisteredObject, dzięki czemu mogę zwolnić te theads, gdy aplikacja jest zamykana, ale to też nie działa. Nadal się zawiesza i nie ma żadnego wzorca, kiedy się zawiesza (co zauważyłem). Jestem prawie pewien, że jest to połączenie statycznych instancji i użycie ManualResetEvent, które go powoduje. Po prostu nie wiem na pewno, jak i jak to naprawić.C# zamrożenie serwera komety IIS

Comet.cs (Mój prosty kometa 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; } 
    } 
} 

mojej klasie czat i serwis internetowy

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); 
      } 
     } 
    } 
} 

Plik Test 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> 

I kod aspx za

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(); 
     } 
    } 
} 

Jeśli ktoś ma dobrą teorię na temat przyczyny i/lub naprawić za pozornie arbitralnych wypadków byłoby mile widziane, jeśli you'ld postu :)

Odpowiedz

1

To pytanie .NET Comet engine ma jakieś linki, które powinien skierować Cię we dobry kierunek. Musisz przyjrzeć się implementacji IHttpAsyncHandler, aby obsłużyć długo działające żądanie komety.

+0

Dzięki! Dam ci spróbować, jak tylko będę mógł. Mam handler http napisałem, aby ominąć ten problem, ale zaimplementowałem IHttpHandler (nie asnyc), więc zdecydowanie spróbuję. Czy myślisz, że można to zrobić bez tworzenia programu obsługi HTTP? Pytam, ponieważ dobrze byłoby stworzyć prostą bibliotekę, która może być z łatwością wykorzystana w serwisie internetowym takim, jaki mam powyżej. –

+1

Nie korzystałem z usługi internetowej, więc nie mogę powiedzieć. Jednak opracowałem serwer kometowy przy użyciu IHttpAsyncHandler i działa świetnie. IIS/http.sys używa ustalonej liczby wątków do przetwarzania przychodzących żądań, jeśli wiążesz je z długimi uruchomieniami lub blokowaniem (.WaitOne), bardzo szybko zabijasz iis. –

+0

Czy ten link http://msdn.microsoft.com/en-us/library/aa480516.aspx z msdn pomaga? Mówi o Async WebMthods. –

Powiązane problemy