在创建聊天系统期间,我使用长生命请求来获取消息,并使用jquery请求发送这样的消息:
* 发送:*
$("#btn").click(function () {
$.ajax({
type: "POST",
url: "Chat.aspx/Insert",
data: "{ 'Str' :'" + $("#txtStr").val() + "' }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
},
error: function () {
}
});
});
接收:
function Refresh() {
$.ajax({
type: "POST",
url: "Chat.aspx/GetRecords",
data: "{ 'Id' : " + $("#hdnV1").val() + "}",
success: function (data) {
$.each($(data.d), function () {
//Show it to user
});
},
complete: function () {
return Refresh();
},
contentType: "application/json; charset=utf-8",
dataType: "json",
traditional: true,
async: true
});
}
这是我的服务器端代码来获取消息:
[WebMethod]
public static object GetRecords(int Id)
{
TestEntities db = new TestEntities();
int count = 0;
while (true)
{
if (count++ >= 300)
return null;
System.Threading.Thread.Sleep(1000);
var list = db.Commets.Where(rec => rec.Id > Id).Select(rec => new { Id = rec.Id, Str = rec.Str }).ToList();
if (list.Count > 0)
return list;
}
}
当用户写入内容并单击“发送”按钮时,请求将进入暂挂状态,因为长寿命请求正在执行
我用萤火虫检查它们,有没有人帮助我!?! 有关详细信息,请评论我,抱歉我的英语语法不好,我是英语新手
由于
答案 0 :(得分:3)
这不是在asp.net中构建聊天的最佳方法。随着用户数量的增加,此方法将无法扩展。
看看SignalR是构建聊天应用程序的不错选择。
但是如果您确实想出于某种原因自己动手,那么在asp.net中构建聊天的最有效方法是使用IHttpAsyncHandler和ajax请求。
Asp.net的工作线程数量有限。即使对于相对较少的用户,将其中一个置于睡眠状态也会导致您的应用程序失效。
异步请求允许您延迟请求的响应,直到发生外部事件 用户调用此处理程序并等待有人向他发送消息 邮件会在您发送给用户后立即发送。
收到消息后,客户端发出另一个请求并等待下一条消息。 这是保持持久连接打开的方式,并允许服务器将数据推送到客户端。
这比查看网站以检查邮件是否已到达要高效得多 使用异步处理程序还可确保在用户等待消息到来时不会浪费任何asp.net线程。使用计时器进行轮询,您将很快用完线程来处理asp.net中的请求。
这确保即使网站的用户数量增加,您的聊天也可以很好地扩展。
这是completely working project that implements this和ajax。
避免使用数据库作为您网站上的用户之间的通信方法。如果要记录聊天记录,请进行所有写入异步调用。
答案 1 :(得分:2)
由于您在评论中写道您在应用程序中使用Session
状态,因此长时间运行的请求阻止更新可能是正确的。
原因是Asp.Net阻止了对Session
的并发访问。有关详细信息,请参阅MSDN上的this link。具体来说(靠近页面底部):
但是,如果对同一会话发出两个并发请求(通过 使用相同的SessionID值),第一个请求获得独占 访问会话信息。第二个请求仅执行 第一个请求完成后。
解决此问题的一种方法可能是在相关网页上设置EnableSessionState="ReadOnly"
或EnableSessionState="False"
。这假设您不需要使用聊天系统访问特定页面中的Session
。
答案 2 :(得分:0)
您也应该异步发送Insert,就像使用GetRecords一样。这应该可以解决你的问题。将async: true
添加到发送请求。
答案 3 :(得分:0)
问题是GetRecords
可能永远不会返回。除非你使用像WebSockets这样的东西,否则这是一个问题。这意味着连接将永远不会完成(直到它超时),并且您很可能不会从中接收任何数据。
你应该做的是让GetRecords
立即返回,然后每隔X秒轮询你的jQuery以获取新记录。
您还可以尝试在while循环中添加Sleep
(以及最大循环限制)以允许其他线程在系统中工作并防止无限循环。即。
int maxLoops = 50;
int loopNum = 0;
while (loopNum < maxLoops)
{
var list = db.Commets.Where(rec => rec.Id > Id).Select(rec => new { Id = rec.Id, Str = rec.Str }).ToList();
if (list.Count > 0)
return list;
Thread.Sleep(250); //Wait 1/4 of a second
loopNum++;
}