【发布时间】:2009-04-14 01:04:03
【问题描述】:
最近,有关 Winforms 应用程序线程的书(Joe Duffy 在 Windows 上进行并发编程)出版了。这本书专注于 winforms,有 1000 页。
ASP.NET 线程有哪些陷阱?我确信在 ASP.NET 中实现线程时需要注意很多问题。我应该注意什么?
谢谢
【问题讨论】:
标签: asp.net
最近,有关 Winforms 应用程序线程的书(Joe Duffy 在 Windows 上进行并发编程)出版了。这本书专注于 winforms,有 1000 页。
ASP.NET 线程有哪些陷阱?我确信在 ASP.NET 中实现线程时需要注意很多问题。我应该注意什么?
谢谢
【问题讨论】:
标签: asp.net
由于 IIS 接收到的每个 http 请求都是单独处理的,因此无论如何都是在它自己的线程上处理的,所以您应该遇到的唯一问题是,如果您在单个 http 请求的范围内启动了一些长时间运行的进程。在这种情况下,我会将此类代码放入一个单独的引用依赖程序集中,像中间层组件一样编码,完全不依赖或耦合到 ASP.Net 模型,并单独处理该程序集中出现的任何并发问题,无需完全担心 ASP.Net 模型...
【讨论】:
Wintellect 的 Jeff Richter 有一个名为 PowerThreading 的库。如果您在 .NET 上开发应用程序,这将非常有用。 => Power Threading Library
查看他在各种活动中的在线演示。
【讨论】:
通常鼓励您在 .Net 中使用线程池,因为它有很多好处,代表您管理事物.....但在 ASP.net 中不。
由于 ASP.net 已经是多线程的,它使用线程池来处理映射到 ASP.net ISAPI 过滤器的请求,并且由于线程池的大小是固定的,使用它基本上就是在使用线程用于处理请求的工作。
在小型、低流量的网站中,这不是问题,但在大型、高流量的网站中,您最终会竞争和消耗 ASP.net 进程所依赖的线程。
如果你想使用线程,可以做类似......
Thread thread = new Thread(threadStarter);
thread.IsBackground = true;
thread.Start();
但带有警告:请确保将 IsBackground 设置为 true,因为如果不是,则线程存在于前台,并且可能会阻止 IIS 工作进程回收或重新启动。
【讨论】:
首先,您是在谈论异步 ASP.NET 吗?还是使用 ThreadPool/启动自己的线程?
如果您不是谈论异步 ASP.NET,那么要回答的主要问题是:您将在其他线程中做什么工作以及该工作是否特定于请求/响应循环,还是更多的是在后台处理全局任务?
编辑
如果您需要为给定的请求/响应周期处理并发操作(比多线程 IMO 更好的术语),请使用 ASP 的异步功能。网。这些提供了 IIS 对并发支持的抽象,允许服务器在当前请求等待工作完成时处理其他请求。
对于全局任务的后台处理,我根本不会使用 ASP.NET。您应该假设 IIS 将在随机时间点回收您的 AppPool。您也不应该假设 IIS 会按任何计划运行您的 AppPool。任何重要的后台处理都应该在 IIS 之外完成,无论是作为计划任务还是作为 Windows 服务。我通常采用的方法是拥有一个 Windows 服务和一个共享的工作队列,网站可以在其中发布工作项。队列可以是数据库表、可靠的基于消息的队列(MSMQ 等)、文件系统上的文件等。
【讨论】:
立即想到的是,为什么要在 ASP.NET 中“实现线程”。
您确实需要始终意识到 ASP.NET 是多线程的,因为许多请求可以在各自的线程中同时处理。因此,例如使用静态字段需要考虑线程。
但是,您很少会想自己在代码中启动一个新线程。
就 UI 中线程的常见 winforms 问题而言,这些问题在 ASP.NET 中不存在。无需担心基于窗口的消息泵。
【讨论】:
可以在 ASP.NET 中创建异步页面。这些将执行所有步骤直到某一点。例如,这些步骤将包括异步获取数据。当所有异步任务都完成后,页面生命周期的剩余部分将执行。同时,工作线程没有被占用等待数据库 I/O 完成。
在此模型中,所有额外线程都在执行,而请求、页面实例和所有控件仍然存在。启动自己的线程时必须小心,在线程执行时,请求、页面实例和控件可能已经被 Disposed。
此外,像往常一样,请确保多线程实际上会提高性能。通常,额外的线程会使事情变得更糟。
【讨论】:
问题与任何多线程应用程序中的问题几乎相同。
处理请求所涉及的类(Page、Controls、HttpContext.Current、...)是特定于该请求的,因此不需要任何特殊处理。
对于您在这些类中作为局部变量或字段实例化的任何类,以及对 Session 的访问,同样如此。
但是,像往常一样,您需要同步对共享资源的访问,例如:
我在 ASP.NET 应用程序中经常看到线程错误,例如一个单例被多个并发请求使用而没有同步,导致用户 A 看到用户 B 的数据。
【讨论】: