代码之家  ›  专栏  ›  技术社区  ›  Martin Ongtangco

c#中正确的队列线程技术?

  •  1
  • Martin Ongtangco  · 技术社区  · 14 年前

    我想实现一个windows服务,该服务将丢弃的以平面分隔的文件捕获到一个文件夹中,以便导入数据库。我最初设想的是让FileSystemWatcher检查导入的新文件,并创建一个新线程来导入。

    4 回复  |  直到 14 年前
        1
  •  0
  •   Brian Rasmussen    14 年前

    Task 对于每条消息。这将在线程池线程上运行代码,从而减少创建线程的开销。

    你也可以做类似的事情 asynchronous delegates 如果.NET 4不是一个选项。但是,在这种情况下,代码会变得更复杂一些。这也将利用线程池,并节省为每条消息创建新线程的开销。

        2
  •  1
  •   Andreas Paulsson    14 年前

    我为一个客户开发了这样的产品。该服务正在监测一些文件夹中的新文件,当发现这些文件时,这些文件将被读取、处理(打印在条形码打印机上)、存档和删除。

    “discoverer”层发现文件并将文件名放入“filereader”层处理的列表中。“discoverer”层通过设置“filereader”层正在等待的事件来表示有新文件要处理。

    在“文件读取器”层读取文件之后,使用线程池.QueueWorkItem处理文件内容。

    处理完文件后,会将原始文件复制到存档并从原始位置删除。存档文件也被定期清理,以防止服务器被淹没。档案很适合故障排除。

    在过去两年多的时间里,它已经在许多不同的环境中用于生产,并且被证明是非常可靠的。

        3
  •  1
  •   Ed Power    14 年前

    我已经派了一个服务也这样做。我通过一个计时器进行轮询,该计时器的已用事件处理程序充当管理器,将新文件添加到队列中,并启动使用队列的可配置数量的线程。一旦处理完文件,它就会重新启动计时器。

    每个线程(包括事件处理程序)都会捕获并报告所有异常。服务总是在运行,我使用一个单独的UI应用程序来告诉服务启动和停止计时器。这种方法已经坚如磐石,而且服务在几年的处理过程中从未崩溃过。

        4
  •  1
  •   Brian Gideon    14 年前

    传统的方法是创建一组有限的线程(可能只有1个),并让它们监视阻塞队列。中的代码 FileSystemWatcher 1 BlockingCollection 类,该类在.NET 4.0中或作为 Reactive Extensions 下载。

    public class Example
    {
      private BlockingCollection<string> m_Queue = new BlockingCollection<string>();
    
      public Example()
      {
        var thread = new Thread(Process);
        thread.IsBackground = true;
        thread.Start();
      }
    
      private void FileSystemWatcher_Event(object sender, EventArgs args)
      {
        string file = GetFilePathFromEventArgs(args);
        m_Queue.Add(file);
      }
    
      private void Process()
      {
        while (true)
        {
          string file = m_Queue.Take();
          // Process the file here.
        }
      }
    }
    

    你可以利用 Task TPL ThreadPool -我喜欢这种方法。您可以为需要处理的每个文件(或者批处理它们)启动一个新任务。我所看到的这种方法的唯一问题是,要控制同时打开的数据库连接的数量会更加困难。这绝对不是一个止步不前,它可能是没有关系。

    1 文件系统监视程序 已经知道有点不稳定,所以经常建议使用第二种方法来发现文件更改,以防它们被 文件系统监视程序 . 在这个问题上,您的里程数可能会有所不同。