【问题标题】:C# - Moving files - to queue or multi-threadC# - 移动文件 - 到队列或多线程
【发布时间】:2009-12-04 18:48:09
【问题描述】:

我有一个应用程序,它使用 Flex 前端和 .NET Web 服务将项目及其文件从预览版转移到生产中。目前,该过程大约需要 5-10 分钟/每个项目。除了延迟问题之外,它真的不应该花那么长时间。我想知道这是否是多线程的好用例。此外,考虑到用户可能想要推送多个项目或一个接一个地推送,有没有办法将作业排队。

非常感谢任何建议和示例。

谢谢!

【问题讨论】:

  • 您是否对此进行了分析以确定为什么它需要比预期更长的时间?
  • roygbiv 是正确的 - 如果您要最大化磁盘或网络带宽,那么多线程毫无意义,这就是它需要这么长时间的原因。找出它为什么这么慢,而不是随机采取纠正措施。
  • 正如 roygbiv 和 Michael 指出的那样,您需要进行一些分析,以免最终优化错误的内容。 5-10 分钟中有多少是处理器、磁盘 i/o 和网络流量。压缩有帮助吗?是否有可以并行完成的任务?您的应用程序是否主要在 Web 服务上等待?即使是一些相当简单的跟踪语句也应该产生一些有用的观察结果。

标签: c# apache-flex multithreading queue


【解决方案1】:

执行大量磁盘 IO 的操作通常不适合多线程,因为磁盘一次只能执行一件事。但是,如果您要推送到多个服务器或服务器具有特别好的磁盘子系统,则一些轻线程可能会有所帮助。

【讨论】:

  • 因为看起来他正在将文件从一台服务器复制到另一台服务器(通常您有不同的服务器用于生产和登台),这样的操作受益于异步 I/O 或线程,在这种情况下,您将读取一个缓冲区,然后在将该缓冲区写入目标时,从源并行读取另一个缓冲区。但在他弄清楚他目前的解决方案为何缓慢之前,没有人能说出究竟什么最有帮助。
【解决方案2】:

请注意 - 无论您是否决定将作业排队,您都将使用多线程。排队只是处理最终使用多线程解决的问题的一种方式。

是的,我建议你建立一个队列来推出每个项目。

【讨论】:

    【解决方案3】:

    您应该将代码的速度与仅在 Windows(即资源管理器或命令行)中复制与使用 TeraCopy 之类的高级功能进行复制进行比较。如果您的代码比 Window 慢得多,请查看代码中的部分以使用探查器进行优化。如果您的代码与 Windows 一样快但比 TeraCopy 慢,那么多线程可能会有所帮助。

    当操作 I/O 受限时,多线程通常没有帮助,但复制文件涉及从磁盘读取和通过网络写入。这是两个 I/O 操作,因此如果将它们分开到不同的线程上,可以提高性能。对于这样的事情,您需要一个生产者/消费者设置,其中您有一个Circular queue,其中一个线程从磁盘读取并写入队列,另一个线程从队列读取并写入网络。重要的是要记住两个线程不会以相同的速度运行,因此如果队列已满,请在写入更多数据之前等待,如果为空,请在写入之前等待。此外,锁定策略可能会对这里的性能产生很大影响,并可能导致性能下降到比单线程实现慢。

    【讨论】:

      【解决方案4】:

      如果您只在两台计算机之间移动东西,网络将成为瓶颈,因此您可能需要将这些操作排队。

      同样,在同一台机器上,I/O 将成为瓶颈,所以你也想在那里排队。

      【讨论】:

      • 磁盘慢了怎么办?如果他一次复制 1 个字节,并使用跨线程边界的同步调用向 GUI 报告进度,或者使用相当于“Application.DoEvents”的东西来确保更新 GUI 以反映他的新进度,该怎么办?我同意在最优解中,网络会成为瓶颈的原则,但你不能说它是他当前解决方案中的瓶颈。跨度>
      【解决方案5】:

      您应该尝试使用线程池。

      ThreadPool.QueueUserWorkItem(MoveProject, project);
      

      【讨论】:

      • FileStream 怎么样,他也应该使用它吗?
      • 我猜你是在讽刺。我提到这一点的原因是因为它实际上会使代码在 1 行中多线程,而不是滚动您自己的排队系统。这意味着他几乎可以立即看到是否有好处。
      • 顺便说一句,仅仅因为你有 33k 点并不能让你成为一个势利的混蛋。
      【解决方案6】:

      同意每个人对并行运行任务的有限性能的看法。

      如果您可以完全控制您的部署环境,您可以使用 Rhino Queues:

      http://ayende.com/Blog/archive/2008/08/01/Rhino-Queues.aspx

      这将允许您异步生成作业队列(例如从您的 Silverlight/Flex 应用程序调用的 WCF 服务)并同步使用它们。

      您也可以使用 WCF 和 MSMQ,但学习曲线更长。

      【讨论】:

        【解决方案7】:

        当使用多线程处理多个文件时,通常考虑性能的好主意。主要原因是现在大多数磁盘都支持native command queuing

        我最近在 ddj.com 上写了一篇关于读取/写入具有多个文件的文件的文章。

        http://www.ddj.com/go-parallel/article/showArticle.jhtml?articleID=220300055

        另见相关问题 Will using multiple threads with a RandomAccessFile help performance?

        特别是我的经验是,在处理非常多的文件时,使用多个线程的好主意。相反,在许多情况下使用多线程并不会像通常预期的那样减慢应用程序的速度。

        话虽如此,我想说除了尝试所有可能的不同方法之外,没有其他方法可以找出答案。这取决于很多条件:硬件、操作系统、驱动程序等。

        【讨论】:

          【解决方案8】:

          您应该做的第一件事是将任何类型的分析工具指向您的软件。如果您不能这样做(例如,如果您没有这样的工具),请插入日志记录代码。

          您需要做的第一件事是弄清楚什么需要很长时间才能完成,然后为什么需要很长时间才能完成。您的“复制”操作作为一个整体需要很长时间才能完成还不够好,您需要将其原因归结为一个方法或一组方法。

          在您这样做之前,您可以对代码执行的所有其他操作都可能只是猜测。我的经验告诉我,在性能方面,运行缓慢的 10 个原因中有 9 个让编写代码的人感到惊讶。

          所以先衡量,然后改变。

          例如,您可能会发现您实际上是在报告使用对 UI 的同步调用将文件逐字节复制到 GUI 的进度,在这种情况下,这无关紧要实际复制的运行速度有多快,您仍然会受到消息处理速度的限制。

          但这只是猜测,直到你知道,所以先测量,然后改变。

          【讨论】:

          • 你说得对,我没有分析工具。我使用 VS Professional 而不是 Team Development 版本。 - 你是什么意思记录代码?断点?谢谢!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-29
          • 2018-09-20
          • 2011-03-13
          • 2010-10-28
          • 1970-01-01
          • 2013-07-20
          • 1970-01-01
          相关资源
          最近更新 更多