3

在 .Net 4.0 框架上使用 C#,我有一个 Windows 窗体主线程(直到现在唯一的一个)等待文件系统事件,然后必须对这些事件提供的文件开始一些预定义的处理。

我打算做以下事情:

  • A1。在主进程启动时立即创建一个单独的线程;
  • A2。让主线程将要处理的文件名放入队列(FIFO)中;
  • A3。每隔 n 秒由计时器触发新线程;
  • A4。让新线程读取队列,如果有项目要执行处理,则让它取消刚刚处理的队列项目。

因为我以前从未编写过线程(我基本上使用 Albahari 作为我的指南针)但我绝对想要,我有几个问题只是为了提前发现可能的严重头痛:

  • Q1。如果主进程只写而新进程只取消队列项,我是否会在队列上遇到并发问题?换句话说:在这种情况下,同步是一个重要问题吗?
  • Q2。我已经看到我可以从头开始创建一个新线程,或者可以重用现有池中可用的线程之一。在这种情况下使用池中的线程更安全/更简单?
  • Q3。让新线程无限期地保持活动状态并且只响应计时器直到主进程关闭有什么缺点吗?
4

1 回答 1

2

如果您的目标是 .Net Framework 4,那么Blocking Collection听起来可以解决您的问题;即当“工作”项在队列上可用时创建一个新的线程池线程(添加新文件时添加到事件处理程序的队列中)并在该线程上异步处理它们。

您可以在生产者/消费者队列中使用一个:

例如:

/// <summary>
/// Producer/consumer queue. Used when a task needs executing, it’s enqueued to ensure order, 
/// allowing the caller to get on with other things. The number of consumers can be defined, 
/// each running on a thread pool task thread. 
/// Adapted from: http://www.albahari.com/threading/part5.aspx#_BlockingCollectionT
/// </summary>
public class ProducerConsumerQueue : IDisposable
{
    private BlockingCollection<Action> _taskQ = new BlockingCollection<Action>();

    public ProducerConsumerQueue(int workerCount)
    {
        // Create and start a separate Task for each consumer:
        for (int i = 0; i < workerCount; i++)
        {
            Task.Factory.StartNew(Consume);
        }
    }

    public void Dispose() 
    { 
        _taskQ.CompleteAdding(); 
    }

    public void EnqueueTask(Action action) 
    { 
        _taskQ.Add(action); 
    }

    private void Consume()
    {
        // This sequence that we’re enumerating will block when no elements
        // are available and will end when CompleteAdding is called.
        // Note: This removes AND returns items from the collection.
        foreach (Action action in _taskQ.GetConsumingEnumerable())
        {
            // Perform task.
            action();
        }
    }
}
于 2012-10-12T10:42:41.377 回答