2009-02-18 3 views
1

У меня есть служба Windows, которая запускает метод, когда истекает срок службы основного таймера (OnElapse).Как я могу управлять элементами в ThreadPool?

Метод OnElapse получает список XML-файлов для обработки. Каждый XML-файл вставляется в ThreadPool.

Я хочу, чтобы я не вставлял 2 XML с тем же именем в ThreadPool.

Как я могу управлять тем, какие элементы находятся в ThreadPool? Я в основном хочу это сделать:

if xmlfilename not in threadpool 
    insert in threadpool 

ответ

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

Это не надежное решение. В коде есть по крайней мере одно условие гонки. А именно, что элемент можно удалять из пула, пока вы пытаетесь его добавить, и на самом деле он не будет добавлен. Но если ваши вопросы касаются только того, что они обрабатываются один раз, это не имеет значения.

+0

Вау, наши решения удивительно похожи, но мне нравится помещать удаление в блок finally, он подчеркивает необходимость удаления элемента независимо от результата обработки. –

+0

Кроме того, я не думаю, что назвал бы это истинное состояние гонки или даже недостаток в решении. –

+0

На самом деле другой файл XML не попадет на сервер до завершения его обработки, поэтому состояние гонки никогда не произойдет. Спасибо, выделите! – Blankman

0

OnElaspe Вы не можете переименовать xml-файл? поэтому он имеет имя unqiue в threadpool.

+0

На самом деле я не хочу, чтобы добавить его в пул т.е. только процесс уникальные файлы xml за раз (бизнес-требование) – Blankman

0

Не могли бы вы сделать словарь> и проверить это, прежде чем делать ввод? Что-то вроде этого ...

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.

+0

, но как только поток завершится, как я собираюсь удалить имя файла из словаря? Это потоки? – Blankman

+0

Это потокобезопасный, если у вас есть словарь, определенный в вашем сервисе. Вы можете обойтись с помощью ThreadPool для ключа в вашем словаре, установив еще одну коллекцию, чтобы связать ваши ThreadPools с типом значений, например Integer. Я предполагаю, что вы знаете, что такое имя файла, когда поток завершается? –

+0

Да, я знаю имя, когда оно завершается, правда! – Blankman

2

Нечто подобное должно сделать это (используйте HashSet вместо словаря, если вы используете .NET 3.5 или выше):

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

<уходит на исследование HashSet> :-) –