我有一个Windows服务,当服务主计时器过去时(OnElapse)运行一个方法。
OnElapse方法获取要处理的.xml文件列表。 每个xml文件都插入到ThreadPool中。
我想确保不会将2个具有相同名称的XML插入到ThreadPool中。
如何管理ThreadPool中的项目?我基本上想要这样做:
if xmlfilename not in threadpool
insert in threadpool
答案 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编码。