2011-06-03 121 views
9

在winforms开发中,您可以创建BackgroundWorker以避免在长时间运行的进程中锁定UI。在ASP.NET中,POST/GET基本上冻结直到完成。我不明白如何添加Thread对此过程有任何好处。也许如果Thread加速完成(比如说在一个多核服务器上),它可能会加快速度。多线程在asp.net中有意义吗?

在一般意义上,我可以使用AJAX进行长时间调用而不会导致网页“冻结”。从这个意义上说,AJAX可以被认为是线程的替代品。

是吗?线程在ASP.NET上几乎毫无用处?

+0

参考:http://msdn.microsoft.com/en-us/magazine/cc163725.aspx(异步页中ASP.NET 2.0) – sisve 2011-06-04 07:08:56

回答

5

多线程可以请求更快,如果:

  1. 每个Web请求的工作可以分解为可并行
  2. 运行每个这样的任务多任务是非常消耗CPU(CPU bound),或者你在不同的I/O路径上有多个I/O绑定任务(请参阅注释)
  3. 您可以使用fork/join parallelism来实现它们。

在这种情况下,你确实可以在ASP.NET中使用多线程。人们犯的一个常见错误是产生线程,然后不等待它们完成 - 例如“我将在用户在后台线程上将其购买记录到数据库时对用户作出响应。这总是一个坏主意,因为IIS可以并且将回收您的网站运行的应用程序池,并且这些后台线程可能会被无声地中止。

+0

I/O绑定任务也可以获利。它们更常见。 CPU参数不成立。 – 2011-06-03 21:21:45

+0

仅当您有多个绑定在不同I/O路径上的独立I/O绑定任务时(例如,多个磁盘或磁盘和网络链接。并行化绑定在同一设备上的I/O并不会为您带来任何收益 - 实际上,对于磁盘,它通常会让您失望。无论如何,回答编辑表明这一点。 – 2011-06-03 21:36:56

+0

两个磁盘操作是可疑的,但是disk/webservice/db的任何组合都是主要的候选项。 2项服务或2项查询可能有资格。 – 2011-06-03 22:30:44

1

如果您需要返回响应并且不想绑定服务器线程,那么在服务器端编程中,线程可能非常有用,特别是对于导致请求超时的长时间运行的进程而言。

+0

IIS通常处理这在大多数情况下,ASP.NET。 – Nate 2011-06-03 20:03:38

1

一个线程可能用于比页面请求的生命周期更长的动作,所以是的,这是有道理的。

一个例子是一个线程,它激活一个进程来编码视频。由于这可能需要一些时间,客户端可以稍后通过AJAX或Comet的编码进度或任何其他数量的机制进行更新。

+0

伟大的一点。我没有想到这一点。 – Nate 2011-06-03 20:03:52

+4

这几乎总是一个坏主意。 IIS不是后台任务友好的。这些任务应该卸载到Windows服务。 – 2011-06-03 20:04:37

1

这取决于工作量和用例。请求/响应系统最好通过在客户端上异步执行它们来提供服务。

如果服务器上的工作负载引发线程化,可以并行完成工作,但每个线程应该在最后连接以返回单个响应。

底线是,如果你得到可以加载并行更快的数据,这样做,否则使用异步(AJAX)从客户端调用,以防止用户界面阻塞

0

我不会甚至可以说ASP.NET中的线程是无用的,但它绝对是一种不同的模型。对于一般的资源请求(页面请求),线程由系统处理。也就是说,来自用户1的请求A可能比用户2的请求B花费更长的时间,而后者不会受到前者的阻碍。按照您的建议将该概念应用于AJAX请求,并且默认情况下整个模型将变为多线程,并可扩展至硬件可处理的任何内容。

产生线程可以是有用的,如果由于某种原因,请求必须产卵一些长期运行的进程,需要在该过程完成之前,向用户作出响应。一般来说,非现场流程应该从Web应用程序中重新分解并放入他们自己的后端服务中。但对于一个页面请求产生一个预计在后台执行某些操作几分钟的线程的浏览器,并不是完全没有听过,因为浏览器不会等待整个时间(可能会超时)。

1

下面是如何仍然可以在ASP.NET编程模型中使用多个线程的具体示例。这个例子假定你可以分解将页面加载到独立工作项目所需的任务,然后你可以并行处理这些工作项并等待它们完成,我使用Task Parallel Library来抽象出线程的显式创建,但结果都是一样的。ASP.NET编程当然可以适应并受益于多线程设计。

private void Page_Load(object sender, EventArgs e) 
{ 
    ICollection<WorkItem> workitems = GetWorkItems(); 

    Parallel.ForEach(workitems, 
    (item) => 
    { 
     ProcessWorkItem(item); 
    }); 

    // Now that we have all of our work items completed we can continue loading the page. 
}