How to reuse a Process instance with slightly different ProcessStartInfo instances?

旧巷老猫 提交于 2019-12-10 15:48:45

问题


I have the following code that starts robocopy as a Process. I also need to do database queries to determine which directories I need to copy each time robocopy is called so I used ProcessStartInfo to control the arguments passed.

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)));
    }
}

How can I reuse Process instances returned by the static Process.Start(ProcessStartInfo) inside the foreach loop and how can I Dispose of them properly?


回答1:


You cannot re-use a Process object. The Process class behaves like all of the other .NET classes that wrap an operating system object. Like Socket, Bitmap, Mutex, FileStream, etcetera. They are tiny little cookies that are very cheap to bake and take very little space on the GC heap. They track the lifetime of the underlying OS object carefully, once the object is dead, the .NET wrapper object is no longer useful either.

The Process class signals that the cookie was eaten with its Exited event and HasExited property. It has some post-bite properties that are useful, ExitCode and ExitTime.

But that's where it ends, if you want to create another process then you have to bake another cookie. Simple to do with the new keyword or the Start() factory function. Don't try to optimize it, there's no point and it can't work. Re-using ProcessStartInfo is fine, it is not a wrapper class.




回答2:


You don't really need to reuse the Process class - that's just a wrapper for the underlying process. And when processes end, they're gone, completely - that's the main point of having a process in the first place.

Instead, it seems like you really want to just make sure that only one of those robocopy processes runs at a time, which is pretty easy:

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.
    }
}


来源:https://stackoverflow.com/questions/30295096/how-to-reuse-a-process-instance-with-slightly-different-processstartinfo-instanc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!