如何重用具有略微不同的ProcessStartInfo实例的Process实例?

时间:2015-05-18 04:26:02

标签: c# .net entity-framework robocopy

我有以下代码作为Process启动robocopy。我还需要进行数据库查询以确定每次调用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)));
    }
}

如何在Process循环中重用static Process.Start(ProcessStartInfo)返回的foreach个实例,我怎样才能正确地Dispose

2 个答案:

答案 0 :(得分:8)

您无法重复使用Process对象。 Process类的行为与包装操作系统对象的所有其他.NET类一样。像Socket,Bitmap,Mutex,FileStream等。它们是很小的小饼干,它们非常便宜,可以在GC堆上占用很少的空间。它们仔细跟踪底层OS对象的生命周期,一旦对象死了,.NET包装器对象也不再有用。

Process类表示cookie已被Exited事件和HasExited属性吃掉。它有一些有用的后咬合属性,ExitCode和ExitTime。

但是它结束了,如果你想创建另一个进程,那么你必须烘焙另一个cookie。简单地使用 new 关键字或Start()工厂函数。不要试图优化它,没有意义,它无法工作。重用ProcessStartInfo很好,它不是包装类。

答案 1 :(得分:1)

您并不需要重复使用Process类 - 它只是基础流程的包装器。当流程结束时,它们完全消失了 - 这是首先制定流程的主要目的。

相反,您似乎确实希望确保一次只运行其中一个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.
    }
}