【发布时间】:2015-08-17 00:33:10
【问题描述】:
我正在编写一个程序,将 csv 文件从“队列”文件夹移动到“处理”文件夹,然后启动名为 import.exe 的第三方进程,将 csv 文件路径作为参数。 Import.exe 是一项长期运行的任务。
我需要程序继续运行并检查队列中的新文件。出于这个原因,我选择了一个 Windows 服务应用程序,因为它会长时间运行。
我的问题是我被各种选项压得喘不过气来,不知道我应该使用background threads 还是parallel programming 来解决这个问题,或者很可能是两者的结合。
到目前为止,我的这段代码只是同步运行。 您会很快看到,目前我只是在疯狂地启动进程,而无需管理或检查是否完成。我已经注释掉了 process.WaitForExit () 显然这是一个阻塞调用。
public int maxConcurrentProcesses = 10;
protected override void OnStart(string[] args)
{
// Set up a timer to trigger every minute.
System.Timers.Timer timer = new System.Timers.Timer(60000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
timer.Start();
}
private void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
// How many instances of import.exe are running?
Process[] importProcesses = Process.GetProcessesByName("import");
int countRunning = importProcesses.Count();
// If there are less than maxConcurrentProcesses, create as many as needed to reach maxConcurrentProcesses
if (countRunning < maxConcurrentProcesses)
{
int processesToStart = maxConcurrentProcesses - countRunning;
for (int i = 0; i < processesToStart; i++)
{
FireOffImport();
}
}
}
private void FireOffImport()
{
// Get the first file returned from the Queue folder
string filePathSource = GetNextCSVInQueue();
if (filePathSource != "")
{
// …
// commandArguments = create our arguments here
// …
// Move the file to processing folder here
// …
// Give a new process the import tool location and arguments
ProcessStartInfo startInfo = new ProcessStartInfo(importLocation + "\\import.exe", commandArguments);
try
{
Process process = Process.Start(startInfo);
// process.WaitForExit(20000);
// If the process has exited, there will be 4 csv files created in the same directory as the file.
}
catch (Exception ex)
{
// Deal with exception here
}
}
}
我还尝试创建一个任务数组,并异步运行这些任务。但最后我仍然必须调用 Task.WaitAll() 才能读取结果。因此,即使提前完成,它也必须等待运行时间最长的任务。
我想我需要尝试循环通过异步创建进程可能使用任务,但我不明白如何将其作为后台进程执行,以便我可以让服务计时器在需要时检查进程数创造更多。
【问题讨论】:
-
在
Task.WaitAll()旁边,还有Task.WaitAny()可以帮助您解决问题中描述的问题。我首先考虑的一般设计是,每个任务都完成一项工作,包括生成import.exe的实例并等待它完成。使用您的文件系统观察程序(例如),您可以检测文件夹中的更改,并为每个更改(新文件)安排一个任务。除非您想限制处理并仅检查间隔而不是立即对更改做出反应,否则计时器在这里并不是必需的。 -
您应该更正的一个问题:考虑如果其他一些软件碰巧使用名为“import.exe”的进程会发生什么。 (而不是计算具有给定名称的进程数,您应该跟踪已启动的特定进程。)
-
那是@HarryJohnston。有了给出的答案,我认为我不需要再跟踪正在运行的进程数量了。如果我继续使用问题中的代码,我会保留一个进程 ID 列表。确保在进程退出时将它们从列表中删除。
-
是的,接受的答案隐含地解决了这个问题 - 您通过将每个过程与单独的任务相关联来跟踪过程。 :-)
标签: c# multithreading asynchronous windows-services .net-4.5