如何管理ThreadPool中的项目?

时间:2009-02-18 17:15:21

标签: c# .net multithreading windows-services

我有一个Windows服务,当服务主计时器过去时(OnElapse)运行一个方法。

OnElapse方法获取要处理的.xml文件列表。 每个xml文件都插入到ThreadPool中。

我想确保不会将2个具有相同名称的XML插入到ThreadPool中。

如何管理ThreadPool中的项目?我基本上想要这样做:

if xmlfilename not in threadpool
   insert in threadpool 

4 个答案:

答案 0 :(得分:4)

这很有把戏,因为你需要密切监视ThreadPool,它需要一种同步形式。这是一个快速而肮脏的例子,说明了这一点。

class XmlManager {
  private object m_lock = new object();
  private HashSet<string> m_inPool = new HashSet<string>();

  private void Run(object state) {
    string name = (string)state;
    try { 
      FunctionThatActuallyProcessesFiles(name);
    } finally { 
      lock ( m_lock ) { m_inPool.Remove(name); }
    }
  }

  public void MaybeRun(string xmlName) { 
    lock ( m_lock ) { 
      if (!m_pool.Add(xmlName)) {
        return;
      }
    }
    ThreadPool.QueueUserWorkItem(Run, xmlName);
  }
}

这不是一个万无一失的解决方案。代码中至少有一个竞争条件。也就是说,当您尝试将其添加回来时,可能正在从池中删除项目,并且实际上不会添加该项目。但如果你只关心他们被处理一次,这没关系。

答案 1 :(得分:2)

这样的事情应该这样做(如果你使用.Net 3.5或更高版本,则使用HashSet而不是字典):

using System;
using System.Collections.Generic;
using System.Threading;

namespace Something
{
    class ProcessFilesClass
    {
        private object m_Lock = new object();
        private Dictionary<string, object> m_WorkingItems = 
            new Dictionary<string, object>();
        private Timer m_Timer;

        public ProcessFilesClass()
        {
            m_Timer = new Timer(OnElapsed, null, 0, 10000);
        }

        public void OnElapsed(object context)
        {
            List<string> xmlList = new List<string>();
            //Process xml files into xmlList

            foreach (string xmlFile in xmlList)
            {
                lock (m_Lock)
                {
                    if (!m_WorkingItems.ContainsKey(xmlFile))
                    {
                        m_WorkingItems.Add(xmlFile, null);
                        ThreadPool.QueueUserWorkItem(DoWork, xmlFile);
                    }
                }
            }
        }

        public void DoWork(object xmlFile)
        {
            //process xmlFile
            lock (m_Lock)
            {
                m_WorkingItems.Remove(xmlFile.ToString());
            }
        }
    }
}

答案 2 :(得分:0)

OnElaspe你不能重命名xml文件吗?所以它在线程池上有一个唯一的名称。

答案 3 :(得分:0)

你不能写字典&gt;并在插入之前检查一下?像这样......

Dictionary<ThreadPool, List<String>> poolXmlFiles = new Dictionary<ThreadPool, List<String>>();
if(poolXmlFiles.ContainsKey(ThreadPool) && !poolXmlFiles[ThreadPool].Contains(xmlFileName))
{
     poolXmlFiles[ThreadPool].Add(xmlFileName);
     //Add the xmlFile to the ThreadPool
}

很抱歉,如果有语法错误,我最近在VB编码。