IHTTPassynchandler和ASP.NET出现问题”;“执行请求”;柜台
解决:我找到了解决这个问题的办法。不知道为什么会发生这种情况,但将应用程序池类型从“集成”切换到“经典”解决了这个问题。现在“正在执行的请求”不断增加,实际的应用程序池进程线程仍然很低(约31个线程),并且应用程序的响应速度非常快(应该如此)。IHTTPassynchandler和ASP.NET出现问题”;“执行请求”;柜台,asp.net,iis-7,Asp.net,Iis 7,解决:我找到了解决这个问题的办法。不知道为什么会发生这种情况,但将应用程序池类型从“集成”切换到“经典”解决了这个问题。现在“正在执行的请求”不断增加,实际的应用程序池进程线程仍然很低(约31个线程),并且应用程序的响应速度非常快(应该如此)。 我使用的是.NET2.0,所以可能有一个问题——我试图用谷歌搜索它,但没有成功。 看见 再次感谢大家。 ps.该代码用于在线玩台球-windows(免费)版本,供好奇和有勇气尝试的人使用:) 你好, 我实现了一个IHTTPassynchandler
我使用的是.NET2.0,所以可能有一个问题——我试图用谷歌搜索它,但没有成功。
看见
再次感谢大家。
ps.该代码用于在线玩台球-windows(免费)版本,供好奇和有勇气尝试的人使用:)
你好, 我实现了一个IHTTPassynchandler,客户端应用程序“轮询”以等待服务器通知。通知由服务器上的其他“活动”生成,异步处理程序根本不工作 执行步骤如下:
IHttpAsyncHandler.BeginProcessRequest
Create AsyncResult instance and add it to a "registered clients" collection
return the AsyncResult
…其他服务器活动将生成要发送到已注册客户端的通知
问题是:
我已经在IIS7上用windowsserver2008sp2和1cpu内核在一个VM上测试了这个。在12个客户端注册通知后(使用Async.ashx上的HTTP GET),性能会下降到后续客户端无法连接的程度
当我检查ASP.NET性能计数器时,“Requests Executing”(请求执行)计数器会随着每个客户端注册而上升,并保持在12(这似乎是它的最大值-可能是每个CPU的线程池大小)
我觉得这很令人困惑。我认为异步处理程序的全部目的是为其他连接释放线程。看来情况并非如此,所以我一定是做错了什么
为什么ASP.NET在等待AsyncResult完成时使用线程?这是配置问题吗?我是否需要做一些特定的事情来表明这是一个异步处理程序
谢谢,,
尼科斯
编辑:在下面添加代码:还有一件事要检查。如果您的客户端不是一个实际的浏览器,而是另一个向您的服务器发出多个并发请求的应用程序,那么这可能会导致您的问题 并发请求和会话状态
对ASP.NET会话状态的访问在每个会话中是独占的,这意味着如果两个不同的用户同时发出请求,则会同时授予对每个单独会话的访问权限。但是,如果对同一会话发出两个并发请求(通过使用相同的SessionID值),则第一个请求将以独占方式访问会话信息。第二个请求仅在第一个请求完成后执行。(如果由于第一个请求超过锁定超时而释放了对信息的独占锁定,则第二个会话也可以访问。)如果@Page指令中的EnableSessionState值设置为ReadOnly,则对只读会话信息的请求不会导致对会话数据的独占锁定。但是,会话数据的只读请求可能仍需要等待会话数据的读写请求设置的锁才能清除。以下是一篇博客文章,解释了您看到的内容: 和伴生岗位 在集成管道模式下,使用默认配置,IIS7将每个CPU的并发请求(非线程)限制为12。您可以通过修改配置来更改此设置
我不能放手。我很确定这就是你看到的。深入研究这篇文章,我真的不喜欢他们所做的改变,因为这显然会导致这样的问题,但我该评判谁呢 我认为您需要发布更详细的代码。这听起来像是由于未能正确实现异步模式而导致的某种“泄漏”,但很难说。完成-真的很简单。如果您需要澄清,请让我知道。RegisteredClient.Instance.Add()无法出于任何原因阻止,对吗?还有一个问题-在您使用的模式中,我只会为completedsynchronously属性返回“false”。在调用CompleteCall()时,是否存在将该参数设置为true的情况?@Joe不,没有。我先查过了。它几乎立即返回(不到一毫秒),是的,在某些情况下,它可以同步完成。当有未完成的通知时会发生这种情况。我还验证了让它永久返回false并没有什么区别@ZERO:如果真是这样,我会非常惊讶。如果它这样做,它的行为就像一个正常的同步处理程序。我认为IAsyncResult会进入asp.net监视的队列。是的,应用程序不是浏览器。会话状态使用以下命令禁用:in web.configbriant!非常感谢——至少我现在知道了!
AsyncResult.CompleteCall called as a result of the generated notification(s).
IHttpAsyncHandler.EndProcessRequest is called
The notification(s) attached to the AsyncResult are written to the response stream.
public class AsyncResult : IAsyncResult
{
private AsyncCallback _cb;
private object _state;
private ManualResetEvent _event;
private bool _completed;
private bool _completedsynchronously;
private HttpContext _context;
private byte[] _data;
private int _datalength;
private object _lock = new object();
public AsyncWaitResult(AsyncCallback cb, object state, HttpContext context)
{
_context = context;
_cb = cb;
_state = state;
}
public void Close()
{
if (_event != null)
{
_event.Close();
_event = null;
}
}
public HttpContext Context { get { return _context; } }
public Object AsyncState { get { return _state; } }
public bool CompletedSynchronously { get { return _completedsynchronously; } }
public bool IsCompleted { get { return _completed; } }
public byte[] Data { get { return _data; } }
public int DataLength { get { return _datalength; } }
public WaitHandle AsyncWaitHandle
{
get
{
lock (_lock)
{
if (_event == null)
_event = new ManualResetEvent(_completed);
return _event;
}
}
}
public void CompleteCall(byte[] data, int length, bool completedsynchronously)
{
_data = data;
_datalength = length;
_completedsynchronously = completedsynchronously;
lock (_lock)
{
_completed = true;
if (_event != null)
_event.Set();
}
if (_cb != null)
_cb(this);
}
}
public class Outbound : IHttpAsyncHandler
{
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object state)
{
AsyncResult asyncresult = new AsyncResult(cb, state, context);
RegisteredClients.Instance.Add(asyncresult);
return asyncresult;
}
public void EndProcessRequest(IAsyncResult ar)
{
AsyncResult result = (AsyncResult)ar;
if (result != null)
{
result.Context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
result.Context.Response.ContentType = "application/octet-stream";
result.Context.Response.AddHeader("Connection", "keep-alive");
if (result.Data != null)
result.Context.Response.OutputStream.Write(result.Data, 0, result.DataLength);
result.Close();
}
}
public void ProcessRequest(HttpContext context){}
public bool IsReusable { get { return true; } }
}