如何重用具有稍微不同的 ProcessStartInfo 实例的 Process 实例?
How to reuse a Process instance with slightly different ProcessStartInfo instances?
我有以下代码以 robocopy
作为 Process
开头。我还需要进行数据库查询以确定每次调用 robocopy
时我需要复制哪些目录,因此我使用 ProcessStartInfo
来控制传递的参数。
internal class Program
{
private static void Main(string[] args)
{
using (var context = new MyDbContext())
{
IEnumerable<ProcessStartInfo> processInfos = GetProcessInfos(context, args[0]);
foreach (ProcessStartInfo processInfo in processInfos)
{
// How can I reuse robocopy Process instances and
// how can I dispose of them properly?
Process.Start(processInfo);
}
}
}
private static IEnumerable<ProcessStartInfo> GetProcessInfos(MyDbContext context,
string directory)
{
const string defaultRobocopyFormatString = "{0} {1} /mir /tee /fft /r:3 /w:10 /xd *Temp*";
var directoryInfo = new DirectoryInfo(directory);
return from dir in directoryInfo.GetDirectories()
from myEntity in context.MyEntities
where dir.Name == myEntity.Name
select new ProcessStartInfo("robocopy",
string.Format(defaultRobocopyFormatString,
Path.Combine("C:\Test", dir.Name),
Path.Combine("C:\Test_bak", dir.Name)));
}
}
如何在 foreach
循环中重用 static
Process.Start(ProcessStartInfo)
返回的 Process
个实例,以及如何正确地 Dispose
个实例?
您实际上不需要重用 Process
class - 这只是底层进程的包装器。当流程结束时,它们就完全消失了 - 这就是首先拥有流程的要点。
相反,您似乎真的只想确保这些 robocopy
进程中只有一个进程同时运行,这非常简单:
using (var context = new MyDbContext())
{
IEnumerable<ProcessStartInfo> processInfos = GetProcessInfos(context, args[0]);
foreach (ProcessStartInfo processInfo in processInfos)
{
using (var process = Process.Start(processInfo))
{
// Blocks until the process ends
process.WaitForExit();
}
// When the `using` block is left, `process.Dispose()` is called.
}
}
您不能重复使用 Process 对象。 Process class 的行为类似于包装操作系统对象的所有其他 .NET classes。像 Socket、Bitmap、Mutex、FileStream 等等。它们是非常小的饼干,烘烤起来非常便宜,并且在 GC 堆上占用的空间很小 space。他们仔细跟踪底层 OS 对象的生命周期,一旦对象死亡,.NET 包装器对象也不再有用。
进程 class 表示 cookie 已通过其 Exited 事件和 HasExited 属性 被吃掉。它有一些有用的 post-bite 属性,ExitCode 和 ExitTime。
但这就是它的结束,如果你想创建另一个过程,那么你必须烘烤另一个 cookie。使用 new 关键字或 Start() 工厂函数即可轻松完成。不要试图优化它,没有意义,也不起作用。重新使用 ProcessStartInfo 很好,它不是包装器 class.
我有以下代码以 robocopy
作为 Process
开头。我还需要进行数据库查询以确定每次调用 robocopy
时我需要复制哪些目录,因此我使用 ProcessStartInfo
来控制传递的参数。
internal class Program
{
private static void Main(string[] args)
{
using (var context = new MyDbContext())
{
IEnumerable<ProcessStartInfo> processInfos = GetProcessInfos(context, args[0]);
foreach (ProcessStartInfo processInfo in processInfos)
{
// How can I reuse robocopy Process instances and
// how can I dispose of them properly?
Process.Start(processInfo);
}
}
}
private static IEnumerable<ProcessStartInfo> GetProcessInfos(MyDbContext context,
string directory)
{
const string defaultRobocopyFormatString = "{0} {1} /mir /tee /fft /r:3 /w:10 /xd *Temp*";
var directoryInfo = new DirectoryInfo(directory);
return from dir in directoryInfo.GetDirectories()
from myEntity in context.MyEntities
where dir.Name == myEntity.Name
select new ProcessStartInfo("robocopy",
string.Format(defaultRobocopyFormatString,
Path.Combine("C:\Test", dir.Name),
Path.Combine("C:\Test_bak", dir.Name)));
}
}
如何在 foreach
循环中重用 static
Process.Start(ProcessStartInfo)
返回的 Process
个实例,以及如何正确地 Dispose
个实例?
您实际上不需要重用 Process
class - 这只是底层进程的包装器。当流程结束时,它们就完全消失了 - 这就是首先拥有流程的要点。
相反,您似乎真的只想确保这些 robocopy
进程中只有一个进程同时运行,这非常简单:
using (var context = new MyDbContext())
{
IEnumerable<ProcessStartInfo> processInfos = GetProcessInfos(context, args[0]);
foreach (ProcessStartInfo processInfo in processInfos)
{
using (var process = Process.Start(processInfo))
{
// Blocks until the process ends
process.WaitForExit();
}
// When the `using` block is left, `process.Dispose()` is called.
}
}
您不能重复使用 Process 对象。 Process class 的行为类似于包装操作系统对象的所有其他 .NET classes。像 Socket、Bitmap、Mutex、FileStream 等等。它们是非常小的饼干,烘烤起来非常便宜,并且在 GC 堆上占用的空间很小 space。他们仔细跟踪底层 OS 对象的生命周期,一旦对象死亡,.NET 包装器对象也不再有用。
进程 class 表示 cookie 已通过其 Exited 事件和 HasExited 属性 被吃掉。它有一些有用的 post-bite 属性,ExitCode 和 ExitTime。
但这就是它的结束,如果你想创建另一个过程,那么你必须烘烤另一个 cookie。使用 new 关键字或 Start() 工厂函数即可轻松完成。不要试图优化它,没有意义,也不起作用。重新使用 ProcessStartInfo 很好,它不是包装器 class.