Как я могу управлять, какие элементы находятся в ThreadPool? - PullRequest
1 голос
/ 18 февраля 2009

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

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

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

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

if xmlfilename not in threadpool
   insert in threadpool 

Ответы [ 4 ]

4 голосов
/ 18 февраля 2009

Это довольно хитрый трюк, потому что вам нужно внимательно следить за 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);
  }
}

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

2 голосов
/ 18 февраля 2009

Что-то подобное должно сделать это (используйте 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 голосов
/ 18 февраля 2009

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

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 голосов
/ 18 февраля 2009

OnElaspe вы не можете переименовать файл XML? поэтому у него есть уникальное имя в пуле потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...