Recently, the book on threading for Winforms application (Concurrent programming on Windows by Joe Duffy) was released. This book, focused on winforms, is 1000 pages.
最近,出版了关于Winforms应用程序线程的书(由Joe Duffy在Windows上进行并发编程)。本书专注于winforms,共1000页。
What gotchas are there in ASP.NET threading? I'm sure there are plenty of gotchas to be aware of when implementing threading in ASP.NET. What should I be aware of?
ASP.NET线程有什么问题?我确信在ASP.NET中实现线程时需要注意很多问题。我应该注意什么?
Thanks
7 个解决方案
#1
First, are you talking about asynchronous ASP.NET? Or using the ThreadPool/spinning up your own threads?
首先,您在谈论异步ASP.NET吗?或者使用ThreadPool /旋转你自己的线程?
If you aren't talking about asynchronous ASP.NET, the main question to answer is: what work would you be doing in the other threads and would the work be specific to a request/response cycle, or is it more about processing global tasks in the background?
如果你不是在谈论异步ASP.NET,那么要回答的主要问题是:你将在其他线程中做什么工作,工作是否特定于请求/响应周期,还是更多关于处理全局任务在后台?
EDIT
If you need to handle concurrent operations (a better term than multi-threaded IMO) for a given request/response cycle, then use the asynchronous features of ASP.NET. These provide an abstraction over IIS's support for concurrency, allowing the server to process other requests while the current request is waiting for work to complete.
如果您需要为给定的请求/响应周期处理并发操作(比多线程IMO更好的术语),则使用ASP.NET的异步功能。这些提供了对IIS对并发性的支持的抽象,允许服务器在当前请求等待工作完成时处理其他请求。
For background processing of global tasks, I would not use ASP.NET at all. You should assume that IIS will recycle your AppPool at a random point in time. You also should not assume that IIS will run your AppPool on any sort of schedule. Any important background processing should be done outside of IIS, either as a scheduled task or a Windows Service. The approach I usually take is to have a Windows Service and a shared work-queue where the web-site can post work items. The queue can be a database table, a reliable message-based queue (MSMQ, etc), files on the file system, etc.
对于全局任务的后台处理,我根本不会使用ASP.NET。您应该假设IIS将在随机时间点回收您的AppPool。您也不应该假设IIS将以任何类型的计划运行您的AppPool。任何重要的后台处理都应该在IIS之外完成,可以是计划任务,也可以是Windows服务。我通常采用的方法是拥有Windows服务和共享工作队列,网站可以在其中发布工作项。队列可以是数据库表,可靠的基于消息的队列(MSMQ等),文件系统上的文件等。
#2
Since each http request received by IIS is processed separately, on it's own thread anyway, the only issues you should have is if you kick off some long running process from within the scope of a single http request. In that case, I would put such code into a separate referenced dependant assembly, coded like a middle-tier component, with no dependance or coupling to the ASP.Net model at all, and handle whatever concurrency issues arose within that assembly separately, without worrying about the ASP.Net model at all...
由于IIS收到的每个http请求都是单独处理的,无论如何都要在它自己的线程上进行处理,唯一的问题就是如果你从单个http请求的范围内启动一些长时间运行的进程。在这种情况下,我会将这些代码放入一个单独的引用依赖程序集中,编码为中间层组件,根本不依赖或耦合到ASP.Net模型,并分别处理该程序集中出现的任何并发问题,担心ASP.Net模型......
#3
Jeff Richter over at Wintellect has a library called PowerThreading. It is very useful if you are developing applications on .NET. => Power Threading Library
Jeff Richter在Wintellect上有一个名为PowerThreading的库。如果您在.NET上开发应用程序,它非常有用。 =>电源线程库
Check for his presentations online at various events.
在各种活动中在线检查他的演讲。
#4
Usually you are encouraged to use the thread pool in .Net because it of the many benefits of having things managed on your behalf.....but NOT in ASP.net.
通常,我们鼓励您使用.Net中的线程池,因为它具有代表您管理事物的许多好处.....但不在ASP.net中。
Since ASP.net is already multi-threaded, it uses the thread pool to serve requests that are mapped to the ASP.net ISAPI filter, and since the thread pool is fixed in size, by using it you are basically taking threads away that are set aside to do the job of handling request.
由于ASP.net已经是多线程的,它使用线程池来处理映射到ASP.net ISAPI过滤器的请求,并且因为线程池的大小是固定的,所以通过使用它你基本上就是把线程带走了留出来做处理请求的工作。
In small, low-traffic websites, this is not an issue, but in larger, high-traffic websites you end up competing for and consuming threads that the ASP.net process relies on.
在小型,低流量的网站中,这不是问题,但在较大的高流量网站中,您最终会竞争并消耗ASP.net进程所依赖的线程。
If you want to use threading, it is fine to do something like....
如果你想使用线程,可以做像......这样的事情。
Thread thread = new Thread(threadStarter);
thread.IsBackground = true;
thread.Start();
but with a warning: be sure that the IsBackground
is set to true
because if it isn't the thread exists in the foreground and will likely prevent the IIS worker process from recycling or restarting.
但有一个警告:确保IsBackground设置为true,因为如果它不是前台中存在的线程,可能会阻止IIS工作进程回收或重新启动。
#5
The immediate thing that comes to mind is, why would you "implement threading" in ASP.NET.
想到的最直接的事情是,为什么要在ASP.NET中“实现线程化”。
You do need to be conscious all the time that ASP.NET is multi-threaded since many requests can be processed simulatenously each in its own thread. So for example use of static fields needs to take threading into account.
你需要始终注意ASP.NET是多线程的,因为许多请求可以在它自己的线程中进行模拟处理。因此,例如,使用静态字段需要考虑线程。
However its rare that you would want to spin up a new thread in code yourself.
然而,您很少想要自己在代码中启动新线程。
As far as the usual winforms issues with threading in the UI is concerned these issues are not present in ASP.NET. There is no window based message pump to worry about.
对于UI中通常的winforms线程问题而言,这些问题在ASP.NET中并不存在。没有基于窗口的消息泵担心。
#6
It is possible to create asynchronous pages in ASP.NET. These will perform all steps up to a certain point. These steps will include asynchronously fetching data, for instance. When all the asynchronous tasks have completed, the remainder of the page lifecycle will execute. In the meantime, a worker thread was not tied up waiting for database I/O to complete.
可以在ASP.NET中创建异步页面。这些将执行到某一点的所有步骤。例如,这些步骤将包括异步获取数据。完成所有异步任务后,将执行页面生命周期的其余部分。与此同时,工作线程没有等待数据库I / O完成。
In this model, all extra threads are executing while the request, and the page instance, and all the controls, still exist. You have to be careful when starting your own threads, that, by the time the thread executes, it's possible that the request, page instance, and controls will have been Disposed.
在此模型中,所有额外线程都在执行,而请求,页面实例和所有控件仍然存在。在启动自己的线程时必须要小心,在线程执行时,请求,页面实例和控件可能已经被Disposed。
Also, as usual, be certain that multiple threads will actually improve performance. Often, additional threads will make things worse.
此外,像往常一样,确保多个线程实际上会提高性能。通常,额外的线程会使事情变得更糟。
#7
The gotchas are pretty much the same as in any multithreaded application.
陷阱与任何多线程应用程序几乎相同。
The classes involved in processing a request (Page, Controls, HttpContext.Current, ...) are specific to that request so don't need any special handling.
处理请求所涉及的类(Page,Controls,HttpContext.Current,...)特定于该请求,因此不需要任何特殊处理。
Similarly for any classes you instantiate as local variables or fields within these classes, and for access to Session.
类似地,对于任何类,您将实例化为这些类中的局部变量或字段,以及访问Session。
But, as usual, you need to synchronize access to shared resources such as:
但是,像往常一样,您需要同步对共享资源的访问,例如:
- Static (C#) / Shared(VB.NET) references.
- Singletons
- External resources such as the file system ... etc...
静态(C#)/共享(VB.NET)引用。
外部资源,如文件系统......等......
I've seen threading bugs too often in ASP.NET apps, e.g. a singleton being used by multiple concurrent requests without synchronization, resulting in user A seeing user B's data.
我在ASP.NET应用程序中经常看到线程错误,例如:由多个并发请求使用的单例,没有同步,导致用户A看到用户B的数据。
#1
First, are you talking about asynchronous ASP.NET? Or using the ThreadPool/spinning up your own threads?
首先,您在谈论异步ASP.NET吗?或者使用ThreadPool /旋转你自己的线程?
If you aren't talking about asynchronous ASP.NET, the main question to answer is: what work would you be doing in the other threads and would the work be specific to a request/response cycle, or is it more about processing global tasks in the background?
如果你不是在谈论异步ASP.NET,那么要回答的主要问题是:你将在其他线程中做什么工作,工作是否特定于请求/响应周期,还是更多关于处理全局任务在后台?
EDIT
If you need to handle concurrent operations (a better term than multi-threaded IMO) for a given request/response cycle, then use the asynchronous features of ASP.NET. These provide an abstraction over IIS's support for concurrency, allowing the server to process other requests while the current request is waiting for work to complete.
如果您需要为给定的请求/响应周期处理并发操作(比多线程IMO更好的术语),则使用ASP.NET的异步功能。这些提供了对IIS对并发性的支持的抽象,允许服务器在当前请求等待工作完成时处理其他请求。
For background processing of global tasks, I would not use ASP.NET at all. You should assume that IIS will recycle your AppPool at a random point in time. You also should not assume that IIS will run your AppPool on any sort of schedule. Any important background processing should be done outside of IIS, either as a scheduled task or a Windows Service. The approach I usually take is to have a Windows Service and a shared work-queue where the web-site can post work items. The queue can be a database table, a reliable message-based queue (MSMQ, etc), files on the file system, etc.
对于全局任务的后台处理,我根本不会使用ASP.NET。您应该假设IIS将在随机时间点回收您的AppPool。您也不应该假设IIS将以任何类型的计划运行您的AppPool。任何重要的后台处理都应该在IIS之外完成,可以是计划任务,也可以是Windows服务。我通常采用的方法是拥有Windows服务和共享工作队列,网站可以在其中发布工作项。队列可以是数据库表,可靠的基于消息的队列(MSMQ等),文件系统上的文件等。
#2
Since each http request received by IIS is processed separately, on it's own thread anyway, the only issues you should have is if you kick off some long running process from within the scope of a single http request. In that case, I would put such code into a separate referenced dependant assembly, coded like a middle-tier component, with no dependance or coupling to the ASP.Net model at all, and handle whatever concurrency issues arose within that assembly separately, without worrying about the ASP.Net model at all...
由于IIS收到的每个http请求都是单独处理的,无论如何都要在它自己的线程上进行处理,唯一的问题就是如果你从单个http请求的范围内启动一些长时间运行的进程。在这种情况下,我会将这些代码放入一个单独的引用依赖程序集中,编码为中间层组件,根本不依赖或耦合到ASP.Net模型,并分别处理该程序集中出现的任何并发问题,担心ASP.Net模型......
#3
Jeff Richter over at Wintellect has a library called PowerThreading. It is very useful if you are developing applications on .NET. => Power Threading Library
Jeff Richter在Wintellect上有一个名为PowerThreading的库。如果您在.NET上开发应用程序,它非常有用。 =>电源线程库
Check for his presentations online at various events.
在各种活动中在线检查他的演讲。
#4
Usually you are encouraged to use the thread pool in .Net because it of the many benefits of having things managed on your behalf.....but NOT in ASP.net.
通常,我们鼓励您使用.Net中的线程池,因为它具有代表您管理事物的许多好处.....但不在ASP.net中。
Since ASP.net is already multi-threaded, it uses the thread pool to serve requests that are mapped to the ASP.net ISAPI filter, and since the thread pool is fixed in size, by using it you are basically taking threads away that are set aside to do the job of handling request.
由于ASP.net已经是多线程的,它使用线程池来处理映射到ASP.net ISAPI过滤器的请求,并且因为线程池的大小是固定的,所以通过使用它你基本上就是把线程带走了留出来做处理请求的工作。
In small, low-traffic websites, this is not an issue, but in larger, high-traffic websites you end up competing for and consuming threads that the ASP.net process relies on.
在小型,低流量的网站中,这不是问题,但在较大的高流量网站中,您最终会竞争并消耗ASP.net进程所依赖的线程。
If you want to use threading, it is fine to do something like....
如果你想使用线程,可以做像......这样的事情。
Thread thread = new Thread(threadStarter);
thread.IsBackground = true;
thread.Start();
but with a warning: be sure that the IsBackground
is set to true
because if it isn't the thread exists in the foreground and will likely prevent the IIS worker process from recycling or restarting.
但有一个警告:确保IsBackground设置为true,因为如果它不是前台中存在的线程,可能会阻止IIS工作进程回收或重新启动。
#5
The immediate thing that comes to mind is, why would you "implement threading" in ASP.NET.
想到的最直接的事情是,为什么要在ASP.NET中“实现线程化”。
You do need to be conscious all the time that ASP.NET is multi-threaded since many requests can be processed simulatenously each in its own thread. So for example use of static fields needs to take threading into account.
你需要始终注意ASP.NET是多线程的,因为许多请求可以在它自己的线程中进行模拟处理。因此,例如,使用静态字段需要考虑线程。
However its rare that you would want to spin up a new thread in code yourself.
然而,您很少想要自己在代码中启动新线程。
As far as the usual winforms issues with threading in the UI is concerned these issues are not present in ASP.NET. There is no window based message pump to worry about.
对于UI中通常的winforms线程问题而言,这些问题在ASP.NET中并不存在。没有基于窗口的消息泵担心。
#6
It is possible to create asynchronous pages in ASP.NET. These will perform all steps up to a certain point. These steps will include asynchronously fetching data, for instance. When all the asynchronous tasks have completed, the remainder of the page lifecycle will execute. In the meantime, a worker thread was not tied up waiting for database I/O to complete.
可以在ASP.NET中创建异步页面。这些将执行到某一点的所有步骤。例如,这些步骤将包括异步获取数据。完成所有异步任务后,将执行页面生命周期的其余部分。与此同时,工作线程没有等待数据库I / O完成。
In this model, all extra threads are executing while the request, and the page instance, and all the controls, still exist. You have to be careful when starting your own threads, that, by the time the thread executes, it's possible that the request, page instance, and controls will have been Disposed.
在此模型中,所有额外线程都在执行,而请求,页面实例和所有控件仍然存在。在启动自己的线程时必须要小心,在线程执行时,请求,页面实例和控件可能已经被Disposed。
Also, as usual, be certain that multiple threads will actually improve performance. Often, additional threads will make things worse.
此外,像往常一样,确保多个线程实际上会提高性能。通常,额外的线程会使事情变得更糟。
#7
The gotchas are pretty much the same as in any multithreaded application.
陷阱与任何多线程应用程序几乎相同。
The classes involved in processing a request (Page, Controls, HttpContext.Current, ...) are specific to that request so don't need any special handling.
处理请求所涉及的类(Page,Controls,HttpContext.Current,...)特定于该请求,因此不需要任何特殊处理。
Similarly for any classes you instantiate as local variables or fields within these classes, and for access to Session.
类似地,对于任何类,您将实例化为这些类中的局部变量或字段,以及访问Session。
But, as usual, you need to synchronize access to shared resources such as:
但是,像往常一样,您需要同步对共享资源的访问,例如:
- Static (C#) / Shared(VB.NET) references.
- Singletons
- External resources such as the file system ... etc...
静态(C#)/共享(VB.NET)引用。
外部资源,如文件系统......等......
I've seen threading bugs too often in ASP.NET apps, e.g. a singleton being used by multiple concurrent requests without synchronization, resulting in user A seeing user B's data.
我在ASP.NET应用程序中经常看到线程错误,例如:由多个并发请求使用的单例,没有同步,导致用户A看到用户B的数据。