我正在开发一个 Web 应用程序导入程序。目前,管理员用户可以上传我的页面将解析的格式化 csv 文件。我遇到了执行持续时间问题,因为每一行都与必须保存到 Scribd、S3 以及一些内部处理的文件有关。
你们会建议什么来改善执行时间?由于这是一个仅限管理员的页面,我怀疑它每周会运行一次以上,所以我希望尽快将其推出。
我看过一些 Async="true" 标志,但我不确定这是否是我想要的方向,或者我是否应该看起来更像一个 Windows 服务器。
我正在开发一个 Web 应用程序导入程序。目前,管理员用户可以上传我的页面将解析的格式化 csv 文件。我遇到了执行持续时间问题,因为每一行都与必须保存到 Scribd、S3 以及一些内部处理的文件有关。
你们会建议什么来改善执行时间?由于这是一个仅限管理员的页面,我怀疑它每周会运行一次以上,所以我希望尽快将其推出。
我看过一些 Async="true" 标志,但我不确定这是否是我想要的方向,或者我是否应该看起来更像一个 Windows 服务器。
想到两个选择:
线程:在您的代码中设置一组线程,加入它们,然后让每个线程处理一个文件。一旦所有线程完成,您将能够返回页面。这将增加您的周转时间,但仍然可能在页面返回时留下一些不足之处
队列:让用户提交 csv 文件并提供 GUID/Hash/Whatever ID,然后管理员可以转到“状态”页面,输入他们的 ID 并检查他们的工作细节。该解决方案将为用户提供快速反馈,并允许他们跟踪结果而无需等待。
一个快速而肮脏的选择可能是将 Page.Server.ScriptTimeout 设置为该页面上的一个非常高的值。(我认为它在 Int.MaxValue 处达到最大值)。
可能建议在单击提交按钮后阻止它,并通知用户他们可能想去煮咖啡。
我建议使用 AJAX 进行内部回发以处理异步处理。您可以定期轮询状态,并防止您的母版页让“处理”轮在页面上不断搅动以进行冗长的过程。
我有一个网页需要很长时间来处理邮件列表,所以我在它自己的线程中启动它。完成该过程后,可以从结果页面上的另一个链接查看报告。我有一个可运行的 MailSender 类。ASPX 脚本中有一些内容,如下所示:
// 准备 MailSender MailSender ms = new MailSender(people, Subject, FileName....); 如果(发送异步){ ThreadStart ts = new ThreadStart(ms.run); 线程 WorkerThread = new Thread(ts); WorkerThread.Start(); } 别的 { ms.run(); }
如果您想加快代码速度,请尝试将其分解为可并行化的部分,并为每个部分编写一个类。然后,您可以为每个位启动一个新线程并监视某处的状态,以便通知用户何时返回结果。你说你输入的每一行都会生成它自己的输出文件。听起来像是多线程的绝佳候选者。如果您在服务器上没有可用的多核,则不会加快速度。
整个方案的一个问题是服务器重新启动或应用程序池回收将终止您长时间运行的进程。如果您的线程要运行一两个小时,这可能是个问题。
由于处理时间涉及外部因素,您需要考虑性能改进是否会影响“实际”性能,如果大部分时间都在处理它并将其发送给第三方(即Scribd,S3),然后在改进你的结局可能不会产生巨大的影响,并且可能会增加简单任务的复杂性。
我要做的是让 aspx 页面只做 aspx 最擅长的事情;即只处理用户界面部分(即上传),所以一旦上传完成就用户而言,他们的部分就完成了。您可以使用 AJAX 实现进度指示器以使其更好,但作为管理部分,我不会打扰这些细节,
然后让简单的控制台应用程序以特定的时间间隔触发,或者让 Windows 服务监视目录(取决于更新的时间紧迫性),一旦应用程序在后台运行并且不需要用户交互,时间就不需要了一个关键因素(即您没有用户等待返回上下文)..
用户会觉得事情非常快(即上传文件所需的时间),并且您将不必要的复杂性排除在您的解决方案之外。
我认为最简单的解决方案是在 ASP.NET 中使用异步页面。你有什么特别的理由不想走那条路吗?
我可以想到一个替代方案,即有一些后台进程(如由 Windows 中的计划任务或 Windows 服务触发的进程),它将查看等待作业的队列(例如,来自数据库表)并处理那些工作。这样,您必须在某处上传该 CSV 并插入一个数据库记录,以便后台进程将看到该 CSV 并在它出现时使用它。但对我来说,这似乎需要更多的工作,所以我宁愿使用异步页面 :)
这是一个关于 ASP.NET 异步页面的不错的教程