简体   繁体   English

如何管理ThreadPool中的哪些项目?

[英]How can I manage which items are in the ThreadPool?

I have a windows service that runs a method when the services main Timer elapses (OnElapse). 我有一个Windows服务,当服务主计时器经过时(OnElapse),该服务运行一种方法。

The OnElapse method gets a list of .xml files to process. OnElapse方法获取要处理的.xml文件列表。 Each xml file is inserted into a ThreadPool. 每个xml文件都插入一个ThreadPool中。

I want to make sure I don't insert 2 XML's with the same name into the ThreadPool. 我要确保不要将2个具有相同名称的XML插入ThreadPool中。

How can I manage which items are in the ThreadPool? 如何管理ThreadPool中的哪些项目? I basically want to do this: 我基本上想这样做:

if xmlfilename not in threadpool
   insert in threadpool 

This is pretty trick because you need to closely monitor the ThreadPool and it will require a form of synchronization. 这是很技巧,因为您需要密切监视ThreadPool,这将需要一种同步形式。 Here's a quick and dirty example of a way to do this. 这是一个简单而又肮脏的方法示例。

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);
  }
}

This is not a foolproof solution. 这不是万无一失的解决方案。 There is at least one race condition in the code. 代码中至少有一个竞争条件。 Namely that an item could be being removed from the pool while you're trying to add it back in and it won't actually get added. 也就是说,当您试图将其重新添加到某项中时,它可能会从池中删除,而实际上不会被添加。 But if your are only concerned with them being processed a single time, this doesn't matter. 但是,如果您只关心它们一次被处理,那就没关系。

Something like this should do it (use a HashSet instead of a Dictionary if you are using .Net 3.5 or higher): 应该执行以下操作(如果使用的是.Net 3.5或更高版本,请使用HashSet而不是Dictionary):

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());
            }
        }
    }
}

OnElaspe can't you rename the xml file ? OnElaspe您不能重命名xml文件吗? so it has a unqiue name on the threadpool. 因此它在线程池上的名称不明确。

Couldn't you make a dictionary> and check that before you do the insertion? 您能否制作字典>并在插入之前进行检查? Something like this... 像这样

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
}

Sorry if there are syntax errors, I'm coding in VB these days. 抱歉,如果有语法错误,这些天我正在VB中进行编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM