gpt4 book ai didi

c# - 如何 : BeginProcessRequest

转载 作者:可可西里 更新时间:2023-11-01 16:35:24 26 4
gpt4 key购买 nike

编写在 IIS 上运行的服务。

基本上是这样的:

void ProcessRequest(HttpContext context)
{
<Init Stuff>
<Access DB> // This may potentially stall for DB access
<Write Output to conext stream>
}

通过停止 部分中的线程,我们基本上阻止了 IIS 服务线程之一。因此,寻找解决此问题的方法是:

IAsyncResult BeginProcessRequest(HttpContext context,AsyncCallback cb,Object extraData)
{
this.del = new AsyncTaskDelegate(ProcessRequest);
this.del.BeginInvoke(context, cb, extraData);
}
void EndProcessRequest(IAsyncResult result)
{
this.del.EndInvoke(ar);
}

这看起来像是创建了另一个线程来调用 ProcessRequest()。因此,我们仍在 上停滞,但这次我们正在使用不属于 IIS 的线程来停滞。对我来说,这很好而且对称,并且使代码干净且易于阅读。

与一位同事交谈时,他说这不会给你带来任何好处,因为线程仍然停滞不前。我同意,但反驳说它不是 IIS 线程,所以它确实给我买了一些东西。但他声称,如果我们使用 BeginProcessRequest() 来确保唯一的 是异步完成的,那么我们可以购买更多的东西,因为没有线程会停止。

这是伪代码,因为我还没有弄清楚细节:

void ProcessRequest(HttpContext context)
{ /* Do Nothing */ }
IAsyncResult BeginProcessRequest(HttpContext context,AsyncCallback cb,Object extraData)
{
<Init Stuff>
this.command = <Access DB>.getSQLCommand();
this.command.BeginExecuteNonQuery(cb,extraData); // Assume we want to wait for this to complete.
}
void EndProcessRequest(IAsyncResult result)
{
this.command.EndExecuteNonQuery(result);
<Write Output to conext stream>
}

我可以看出这是一个优点,它不会停止执行 BeginExecuteNonQuery() 的线程。但这需要底层实现使用 select() 来检测数据库调用何时实际有数据等待读取。虽然更简单的实现方法是让线程停止等待响应(在这种情况下,添加额外的粒度不会给我带来任何好处)。

那么有没有人有任何引用来表明更好的方法到底是什么?
或者有关于 BeginExecuteNonQuery() 的底层实现如何工作的注释?
或者只是任何可能有帮助的一般信息。

谢谢

编辑:

SqlConnection 类包含一个线程池。

因此,当您对 SqlCommand 执行 BeginExecuteNonQuery() 时,它实际上不需要创建线程。请求被发送,当数据从 SQL-Server 返回时,主控制线程将从池中启动一个线程。因此,上面的选项 3 不会在执行异步数据库操作时不必要地浪费线程或导致线程挂起。

最佳答案

这里的问题是,从逻辑上讲,您仍然需要停止线程。您的进程需要在其 ProcessRequest() 方法中接受 HttpContext,执行某些操作(Db 访问),然后将某些内容写回上下文。

HTTP 的无状态特性意味着打开套接字连接,发出请求,客户端等待响应,然后关闭连接。你没有一个开放的连接只是等待你的处理程序将一些东西写回客户端。在上面的示例中,EndProcessRequest() 在哪里获取其 HttpContext 对象以写入其输出?如果它与传递给 BeginRequest 的是同一个,如果您试图让您的输出返回到该客户端,则它必须是,那么客户端将花费请求和响应之间的全部时间等待 - 同时保持一个开放的连接——让服务器做它的事情并发送一些输出。只要您的单独线程在旋转,该上下文及其相关连接就必须保持打开状态,这意味着您实际上同时阻塞了 ASP.NET 线程。

除非您启动多个线程,否则启动一个额外的线程不会有任何好处,并且可以保证它们将在合理的时间内完成。

此外,这是不必要的。为了使线程执行时间成为一个问题,您将不得不尝试“同时”处理比服务器可以处理的更多的请求。如果您的“数据库访问”方法花费的时间太长,您将最终导致请求排队,最终导致超时。这里的解决方案是使您的响应时间(页面呈现时间和所有数据库访问等呈现所需的时间)尽可能短。

总结:

  1. 不要触发一个额外的线程 - 这仅在您运行多个线程时才有用

  2. 您必须确保您启动的任何其他线程都将在 HTTP 请求的分配时间内完成

  3. 调用 ASP.NET 线程必须等待,直到将响应写回到 Http 上下文,或者直到发生超时。如果您在 ProcessRequest 方法中启动新线程,这可能会导致孤立线程。

简而言之,不要这样做。如果您需要从异步的 BeginRequest 启动进程并且不必将输出写回客户端,请考虑编写一个 Windows 服务来处理这些请求。将每个请求记录到一个表中,并让您的服务轮询该表以查看需要做什么。让您的客户轮询该表以查看结果何时准备就绪(可能通过 AJAX)。这可能不适合您的应用程序,但这是处理此类问题的一种方法。

关于c# - 如何 : BeginProcessRequest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2140466/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com