C# 使用阻止集合创建文件拾取进程
我现在得到的是一个计时器,每5000毫秒触发一次:C# 使用阻止集合创建文件拾取进程,c#,multithreading,blockingcollection,C#,Multithreading,Blockingcollection,我现在得到的是一个计时器,每5000毫秒触发一次: static Timer _aTimer = new System.Timers.Timer(); static void Main(string[] args) { _aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); _aTimer.Interval = 5000; _aTimer.Enabled = true;
static Timer _aTimer = new System.Timers.Timer();
static void Main(string[] args)
{
_aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
_aTimer.Interval = 5000;
_aTimer.Enabled = true;
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
}
fire然后设置处理文件的队列:
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// stop the timer so we dont reprocess files we already have in the queue
StopTimer();
// setup a list of queues
var lists = new List<IncomingOrderQueue>();
//get the accounts in which the files we are looking in
var accounts = new List<string>() { "Account1", "Account2" };
//loop through the accounts and set up the queue
foreach (var acc in accounts)
{
// create the queue
var tmp = new IncomingOrderQueue();
// for each file in the folders add it to be processed in the queue
foreach (var orderFile in OrderFiles(acc))
{
tmp.EnqueueSweep(new QueueVariables() { Account = acc, File = orderFile });
}
// add the queue to the list of queues
lists.Add(tmp);
}
// for each of the queues consume all the contents of them
Parallel.ForEach(lists, l => l.Consume());
//start the timer back up again because we have finished all the files we have in the current queue
StartTimer();
}
public static void StopTimer()
{
Console.WriteLine("Stop Timer");
_aTimer.Stop();
_aTimer.Enabled = false;
}
public static void StartTimer()
{
Console.WriteLine("Start Timer");
_aTimer.Enabled = true;
_aTimer.Start();
}
time-devent上的私有静态void(对象源,ElapsedEventArgs e)
{
//停止计时器,这样我们就不会重新处理队列中已有的文件
停止计时器();
//设置队列列表
var List=新列表();
//获取我们正在查找的文件所在的帐户
var accounts=new List(){“Account1”、“Account2”};
//循环查看帐户并设置队列
foreach(账户中的var acc)
{
//创建队列
var tmp=new IncomingOrderQueue();
//对于文件夹中的每个文件,添加要在队列中处理的文件
foreach(OrderFiles(acc)中的var orderFile)
{
EnqueueSweep(new QueueVariables(){Account=acc,File=orderFile});
}
//将队列添加到队列列表中
列表。添加(tmp);
}
//对于每个队列,都会使用其中的所有内容
Parallel.ForEach(list,l=>l.Consume());
//重新启动计时器,因为我们已完成当前队列中的所有文件
StartTimer();
}
公共静态void StopTimer()
{
控制台写入线(“停止计时器”);
_停止();
_aTimer.Enabled=false;
}
公共静态void StartTimer()
{
控制台写入线(“启动计时器”);
_aTimer.Enabled=true;
_aTimer.Start();
}
阻塞队列本身:
public class IncomingOrderQueue
{
BlockingCollection<QueueVariables> _orderQ = new BlockingCollection<QueueVariables>();
public void EnqueueSweep(QueueVariables incoming)
{
// add items to the queue
_orderQ.Add(incoming);
}
public void Consume()
{
// stop anything been adding to the queue
_orderQ.CompleteAdding();
// consume all the objects in the blocking collection
Parallel.ForEach(_orderQ.GetConsumingEnumerable(), Processor.Order.Object);
}
public int QueueCount
{
get
{
return _orderQ.Count;
}
}
}
公共类IncomingOrderQueue
{
BlockingCollection_orderQ=新BlockingCollection();
public void EnqueueSweep(队列变量传入)
{
//将项目添加到队列中
_orderQ.Add(传入);
}
公共消费()
{
//停止添加到队列中的任何内容
_orderQ.CompleteAdding();
//使用阻塞集合中的所有对象
Parallel.ForEach(_orderQ.getconsumineGenumerable(),Processor.Order.Object);
}
公共整数队列计数
{
得到
{
返回_orderQ.Count;
}
}
}
我所做的工作应该是,启动计时器->停止计时器->触发收集文件夹中所有文件的过程->处理所有文件->重新启动计时器
我忍不住想有更好的方法来做我正在做的事情,尤其是当为帐户创建的队列数量为200-400时
谢谢我想你不需要停下来启动你的生产者和消费者。
BlockingCollection
可以在达到最大容量时阻止生产者,在容量为空时阻止消费者
我也可能从一个BlockingCollection
开始,直到分析显示我需要另一个。根据生产者和消费者的相对速度,您可能需要调整他们的数字。如果它们是IO绑定的,那么它们应该是异步的,并且可以有很多,如果它们是CPU绑定的,那么可能只需要可用的处理器数量
我重做了你的例子,假设IO绑定的生产者和消费者,希望它能给你一些想法。它以10秒的间隔启动生产者,并可以一直运行,直到您通过CanelationToken
取消生产。只有在您取消并完成生产后,您才能完成添加
,以释放被阻止的消费者
public class QueueVariables
{
public string Account {get;set;}
public string File {get;set;}
}
public static ConcurrentQueue<string> GetACcounts()
{
return new ConcurrentQueue<string>(new []
{
"Account1",
"Account2",
"Account3",
"Account4",
"Account5",
"Account6",
"Account7",
"Account8",
"Account9",
"Account10",
"Account11",
"Account12",
});
}
public static List<string> GetFiles(string acct)
{
return new List<string>
{
"File1",
"File2",
"File3",
"File4",
"File5",
"File6",
"File7",
"File8",
"File9",
"File10",
"File11",
"File12",
};
}
public static async Task StartPeriodicProducers(int numProducers, TimeSpan period, CancellationToken ct)
{
while(!ct.IsCancellationRequested)
{
var producers = StartProducers(numProducers, ct);
// wait for production to finish
await Task.WhenAll(producers.ToArray());
// wait before running again
Console.WriteLine("***Waiting " + period);
await Task.Delay(period, ct);
}
}
public static List<Task> StartProducers(int numProducers, CancellationToken ct)
{
List<Task> producingTasks = new List<Task>();
var accounts = GetACcounts();
for (int i = 0; i < numProducers; i++)
{
producingTasks.Add(Task.Run(async () =>
{
string acct;
while(accounts.TryDequeue(out acct) && !ct.IsCancellationRequested)
{
foreach (var file in GetFiles(acct))
{
_orderQ.Add(new UserQuery.QueueVariables{ Account = acct, File = file });
Console.WriteLine("Produced Account:{0} File:{1}", acct, file);
await Task.Delay(50, ct); // simulate production delay
}
}
Console.WriteLine("Finished producing");
}));
}
return producingTasks;
}
public static List<Task> StartConsumers(int numConsumers)
{
List<Task> consumingTasks = new List<Task>();
for (int j = 0; j < numConsumers; j++)
{
consumingTasks.Add(Task.Run(async () =>
{
try
{
while(true)
{
var queueVar = _orderQ.Take();
Console.WriteLine("Consumed Account:{0} File:{1}", queueVar.Account, queueVar.File);
await Task.Delay(200); // simulate consumption delay
}
}
catch(InvalidOperationException)
{
Console.WriteLine("Finished Consuming");
}
}));
}
return consumingTasks;
}
private static async Task MainAsync()
{
CancellationTokenSource cts = new CancellationTokenSource();
var periodicProducers = StartPeriodicProducers(2, TimeSpan.FromSeconds(10), cts.Token);
var consumingTasks = StartConsumers(4);
await Task.Delay(TimeSpan.FromSeconds(120));
// stop production
cts.Cancel();
try
{
// wait for producers to finish producing
await periodicProducers;
}
catch(OperationCanceledException)
{
// operation was cancelled
}
// complete adding to release blocked consumers
_orderQ.CompleteAdding();
// wait for consumers to finish consuming
await Task.WhenAll(consumingTasks.ToArray());
}
// maximum size 10, after that capaicity is reached the producers block
private static BlockingCollection<QueueVariables> _orderQ = new BlockingCollection<QueueVariables>(10);
void Main()
{
MainAsync().Wait();
Console.ReadLine();
}
// Define other methods and classes here
公共类队列变量
{
公共字符串帐户{get;set;}
公共字符串文件{get;set;}
}
公共静态ConcurrentQueue GetACcounts()
{
返回新的ConcurrentQueue(新[]
{
“账户1”,
“会计2”,
“帐户3”,
“帐户4”,
“账户5”,
“帐户6”,
“账户7”,
“帐户8”,
“帐户9”,
“帐户10”,
“账户11”,
“账户12”,
});
}
公共静态列表GetFiles(字符串帐户)
{
返回新列表
{
“文件1”,
“文件2”,
“文件3”,
“文件4”,
“文件5”,
“文件6”,
“文件7”,
“文件8”,
“文件9”,
“文件10”,
“文件11”,
“文件12”,
};
}
公共静态异步任务StartPeriodicProducers(int numProducers、TimeSpan period、CancellationToken ct)
{
而(!ct.iscancellationrequest)
{
var生产者=StartProducers(numProducers,ct);
//等待生产完成
wait Task.WhenAll(producers.ToArray());
//等待,然后再运行
控制台写入线(***等待“+期间);
等待任务。延迟(周期,ct);
}
}
公共静态列表StartProducers(int numProducers、CancellationToken ct)
{
List producingTasks=新列表();
var accounts=GetACcounts();
for(int i=0;i
{
字符串帐户;
while(accounts.TryDequeue(out acct)和&!ct.iscancellationrequest)
{
foreach(GetFiles(acct)中的var文件)
{
_添加(newuserquery.QueueVariables{Account=acct,File=File});
WriteLine(“生成的帐户:{0}文件:{1}”,帐户,文件);
等待任务。延迟(50,ct);//模拟生产延迟
}
}
控制台写入线(“成品”);
}));
}
返回生产任务;
}
公共静态列表StartConsumers(整数消费者)
{
List consumingTasks=新列表();
对于(int j=0;j
{
尝试
{
while(true)
{
var queueVar=\u orderQ.Take(