【问题标题】:Threads vs TPL vs Async Delegates in ASP.NETASP.NET 中的线程、TPL 和异步委托
【发布时间】:2023-09-17 19:54:01
【问题描述】:

我有一个在生产环境中运行良好的应用程序,但我想知道我是否可以更好地实现并发......

ASP.NET .NET 4,C#

基本上,它会即时生成 n 条 sql 语句(目前大约 50 条),然后同时运行它们并将数据写入 .csv 文件。

编辑:首先我创建一个线程来完成所有工作,以便页面请求可以返回。然后在那个线程上......

对于每个 SQL 语句,我使用 TPL 创建一个新任务,并使用数据读取器执行它并将数据写入磁盘。创建最后一个文件后,我将一些摘要数据写入摘要文件并将其全部压缩并提供给用户。

我应该改用线程还是异步委托?

我没有发布代码,因为我只是想知道我的整体方法(即 TPL)是否是这种情况下的最佳选择。

请不要教我创建动态 sql,由于我正在阅读的数据库的技术性并且与问题无关,这是完全必要的。 (它是专有系统的后端。有 7000 多个表)。

【问题讨论】:

  • 确保在对代码进行任何更改之前了解异步和多线程/多任务之间的区别。它们不一样,您可能应该在您的场景中将两者结合起来。
  • 在 ASP.NET 中使用 Task.RunTask.Factory.StartNew 确实是个坏主意。在完成所有任务之前,HTTP 请求不会完成。您实际上只会损害 Web 应用程序的可扩展性。请改用async SqlDataReader API
  • @MarcinJuraszek 我想我理解这两个概念之间的区别。 :) 你能详细说明一下吗?好处?所以也许在数据读取器上调用一些异步方法(没有检查是否有)?当我提到异步委托时,我在想也许我应该将它作为一堆异步回调来完成,每个 sql 查询/写入一个,完成后它会进行压缩....
  • @Noseratio 谢谢,但我已经考虑到了这一点。当用户单击按钮时,我为所有这些东西创建一个单独的线程,然后返回,然后在该线程上创建所有读/写线程。这意味着请求会立即返回。然后页面使用更新面板中的计时器来轮询整个操作的完成情况。
  • @Noseratio:另外,回复:异步 SqlDataReader API,我们使用的是 .net 4 而不是 4.5。不要认为这是可用的。另外,我使用的是 ODBC,因为我同时使用了 Oracle 和 SQL Server,而且使用 System.Data.Odbc 实现起来更容易。

标签: asp.net io delegates task-parallel-library datareader


【解决方案1】:

如果我们在 ASP.Net 中从服务 http 请求的线程开始一个新线程,并且新线程有一个未处理的异常,工作进程将立即崩溃。即使我们使用 WCF 服务并从 ASP.Net 调用它,ASP.Net 线程也会等待结果。因此最好使用任何排队机制,以便请求在队列中,并且队列可以根据处理能力在不同的时间处理。当然,当我们说排队时,我们需要考虑队列失败、重新排队等……但是如果应用程序很大并且需要扩展,那么它是值得的。

【讨论】:

    【解决方案2】:

    我应该改用线程还是异步委托?

    显然,您的后台线程操作跨越了单个 HTTP 请求的边界。在这种情况下,您使用什么 API 来运行此类操作并不重要:Task.RunDelegate.BeginInvokeThreadPool.QueueUserWorkItemnew Thread 或其他任何东西。

    您不应该在 ASP.NET 地址空间内运行冗长的后台线程操作,该操作的生命周期跨越多个 HTTP 请求。虽然实现起来相对容易,但这种方法可能在 IIS 的可维护性、可伸缩性和安全性方面存在问题。为此创建一个 WCF 服务并从您的 ASP.NET 页面调用它:

    How to: Host a WCF Service in a Managed Windows Service.

    【讨论】:

      最近更新 更多