问题
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