控制同时运行的并行任务数

时间:2015-07-31 01:36:59

标签: c# parallel-processing windows-services

我有一个Windows服务应用程序,它有许多不同的工作需要并行完成,并在三个不同的时间表上生成。但是我想确保在任何时候都没有N个任务正在运行。

这不是this question的副本,因为这是关于限制每秒启动的任务数,而不是同时运行的数量。也不是this的副本,因为我的任务是在不同的时间表上,所以不能同时排队。

以下是一些提供上下文的代码:

namespace WindowsService1
{
    public partial class Service1 : ServiceBase
    {
        List<Task> ServiceTasks;
        private List<Timer> ServiceTimers;
        private static int N = 10;

        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            List<double> Times = new List<double>(){1000d,2000d,5000d};
            for(int i = 0; i<3 ; i++)
            {
                 var t = new Timer(Times[i]);
                 t.AutoReset = true;
                 ServiceTimers.Add(t);
            }
            ServiceTimers[0].Elapsed += Timer1Elapsed_DoSomething;
            ServiceTimers[0].Start();
            ServiceTimers[1].Elapsed += Timer2Elapsed_DoSomething;
            ServiceTimers[1].Start();
            ServiceTimers[2].Elapsed += Timer3Elapsed_DoSomething;
            ServiceTimers[2].Start();
        }

         private void Timer1Elapsed_DoSomething(object sender, ElapsedEventArgs e)
         {
            ServiceTasks.Add(Task.Factory.StartNew(() => ServiceWork.DoTask1()));
         }

         private void Timer2Elapsed_DoSomething(object sender, ElapsedEventArgs e)
         {
            ServiceTasks.Add(Task.Factory.StartNew(() => ServiceWork.DoTask2()));
         }

         private void Timer3Elapsed_DoSomething(object sender, ElapsedEventArgs e)
         {
            ServiceTasks.Add(Task.Factory.StartNew(() => ServiceWork.DoTask3()));
         }  
    }
}

如何修改此代码以确保在任何给定时间只运行N个任务?

1 个答案:

答案 0 :(得分:1)

SemaphoreSlim是一个允许你这样做的类。它是N个同时&#34;线程&#34;的锁定。

就像那样:

SemaphoreSlim s = ...;
async Task F() {
 await s.WaitAsync();
 DoWork();
 s.Release();
}

如果你不介意每个线程等待1MB的堆栈使用,你也可以使用同步API。

此:

 Task.Factory.StartNew(() => ServiceWork.DoTask3())

变为:

Task.Run(async () => {
 await s.WaitAsync();
 try {
  ServiceWork.DoTask3();
 } finally {
  s.Release();
 }
});

你可以开始无限数量的这些,他们会自我扼杀。

仍然需要任务列表,以便您可以通过等待所有任务完成并处理错误来干净地关闭服务。