【发布时间】:2015-07-30 02:15:41
【问题描述】:
您好用 TPL 编写 Windows 服务,要求是 Windows 服务应该每隔几分钟或几秒运行一次,并并行执行 4 个任务。我已经实现了以下代码,但有一个疑问,比如
Task[] taskRunners = new Task[Utility.conTaskRunners];
Log("Stating Initiate Tasks::" + DateTime.Now);
Log("Calling InitiateTaskRunner Tasks::" + DateTime.Now);
taskRunners[0] = Task.Factory.StartNew(() => InitiateTaskRunner());
taskRunners[1] = Task.Factory.StartNew(() => ScanTaskRunner());
taskRunners[2] = Task.Factory.StartNew(() => ConvertTaskRunner());
taskRunners[3] = Task.Factory.StartNew(() => ConvertedScanRunner());
Task.WaitAll(taskRunners);
Thread.Sleep(12000);
InitiateTasks();
InitiateTaskRunner 如下所示
public void InitiateTaskRunner()
{
Log("Begening InitiateTaskRunner ::" + DateTime.Now);
string[] subDirs = Directory.GetDirectories(Utility.inputPath);
if (subDirs.Length > 0) //files eixsts go and process it
{
Parallel.ForEach(subDirs, dir =>
{
InitiateTaskWorker(dir);
});
}
//BEFORE I SET signal SHOULD this wait as above is PARALLEL.FOREACH?
_waitOnOne.Set(); //set signal for successor after finish
Log("Ending InitiateTaskRunner ::" + DateTime.Now);
}
类似的其他 3 个 TaskRunners 将是;基本上每个任务运行器都会为每个子目录调用TaskWorker并异步处理文件并吃掉TASK Runner,每个Task Worker将是独立和并发的。 TaskWorker 处理完文件后,文件从一个 taskWorker 到另一个 Task Worker 位置将很快移动,并且下一个 TaskWorker 将拾取,但不会从一个 TaskWorker 触发到另一个 TaskWorker。
这种方法的问题是,有时 2、3 和 4 个任务运行器可能会在不执行任何操作的情况下退出,而第一个任务运行器仍在处理并推送到 taskrunner#2 位置等等。并且来自任务运行器位置 2,3,4 的文件将在下一次迭代中处理。
有没有更好的设计呢?并且任何有关 TPL 中异常处理的帮助都会很棒。
public void ScanTaskRunner()
{
Log("Begening ScanTaskRunner ::" + DateTime.Now);
string[] subDirs = Directory.GetDirectories(Utility.scanPath);
if (subDirs.Length > 0) //files exists so proceed
{
Parallel.ForEach(subDirs, dir =>
{
ScanTaskWorker(dir, false);
});
}
else //no files hence wait for prcedent TASK to complete
{
_waitOnOne.WaitOne();
Parallel.ForEach(Directory.GetDirectories(Utility.scanPath), dir =>
{
ScanTaskWorker(dir, false);
});
}
_waitOnTwo.Set(); //Go successor if waiting for this
Log("Ending ScanTaskRunner ::" + DateTime.Now);
}
public void ConvertTaskRunner()
{
Log("Begening ConvertTasktRunner ::" + DateTime.Now);
string[] subDirs = Directory.GetDirectories(Utility.convertPath);
if (subDirs.Length > 0) //files exists so process as usual
{
Parallel.ForEach(subDirs, dir =>
{
ConvertTaskWorker(dir);
});
}
else //no files hence wait for precedent TASK to complete
{
_waitOnTwo.WaitOne();
Parallel.ForEach(Directory.GetDirectories(Utility.scanPath), dir =>
{
ScanTaskWorker(dir, false);
});
}
_waitOnThree.Set(); //Successor is good to go if waiting
Log("Ending ConvertTasktRunner ::" + DateTime.Now);
}
public void ConvertedScanRunner()
{
Log("Begening ConvertedScanRunner ::" + DateTime.Now);
string[] subDirs = Directory.GetDirectories(Utility.convrtedScanPath);
if (subDirs.Length > 0) //files avaiable process as usual
{
Parallel.ForEach(subDirs, dir =>
{
ConvertedScanTaskWorker(dir);
});
}
else //no files wait until precendent TASK completes
{
_waitOnThree.WaitOne();
Parallel.ForEach(Directory.GetDirectories(Utility.scanPath), dir =>
{
ScanTaskWorker(dir, false);
});
}
Log("Ending ConvertedScanRunner ::" + DateTime.Now);
}
【问题讨论】:
标签: c#-4.0 windows-services task-parallel-library