Reputation: 927
I was executing BCP command through exe and it stucks after copying 50000 rows. I looked at some forums and got to know that if we use StandardOuputReader in code than its max limit of output is near to 50000 rows which is happening to me as well Is there a way i ran redirect output where more than 50000 rows can get out.
This code works here i have
proc.StartInfo.RedirectStandardOutput = false;
but i want to have it as true, to see the outputs.
private static void RunBatch(string Fullfilepath, string BatchFilePathDumpFlatFile)
{
mLogger.Error("RunBatch Start=== >");
mLogger.Error("Batch Filepath " + Fullfilepath + '\n' + "Batch File Directory " + BatchFilePathDumpFlatFile);
Process proc = null;
string targetDir = BatchFilePathDumpFlatFile;
proc = new Process();
proc.StartInfo.WorkingDirectory = targetDir;
proc.StartInfo.FileName = Fullfilepath;
//proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.Arguments = "/c";
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = false;
proc.Start();
proc.WaitForExit();
string output = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
string error = proc.StandardError.ReadToEnd();
proc.WaitForExit();
mLogger.Error("Output from batch " + output);
mLogger.Error("Error From Batch " + error);
}
update 1:
private static void RunBatch(string Fullfilepath, string BatchFilePathDumpFlatFile)
{
mLogger.Error("RunBatch Start=== >");
mLogger.Error("Batch Filepath " + Fullfilepath + '\n' + "Batch File Directory " + BatchFilePathDumpFlatFile);
Process proc = null;
string targetDir = BatchFilePathDumpFlatFile;
proc = new Process();
proc.StartInfo.WorkingDirectory = targetDir;
proc.StartInfo.FileName = Fullfilepath;
//proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.Arguments = "/c";
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
string output = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
string error = proc.StandardError.ReadToEnd();
proc.WaitForExit();
mLogger.Error("Output from batch " + output);
mLogger.Error("Error From Batch " + error);
}
this is what i am using is there a mistake because still BCP hangs and it starts running when i stop the exe of the code.
Upvotes: 1
Views: 513
Reputation: 73442
This is the classic deadlock condition. You should not call WaitForExit
before reading the StandardOutput
fully.
When the output is redirected, process will not terminate before all of its StandardOutput
stream is read. So calling WaitForExit
will wait for the started process to terminate, and child process will wait for the parent process to read the output stream fully before it can finish and thus deadlocks.
Msdn provides the explanation and code sample to avoid deadlock.
Synchronous read operations introduce a dependency between the caller reading from the StandardOutput stream and the child process writing to that stream. These dependencies can result in deadlock conditions. When the caller reads from the redirected stream of a child process, it is dependent on the child. The caller waits on the read operation until the child writes to the stream or closes the stream. When the child process writes enough data to fill its redirected stream, it is dependent on the parent. The child process waits on the next write operation until the parent reads from the full stream or closes the stream. The deadlock condition results when the caller and child process wait on each other to complete an operation, and neither can proceed. You can avoid deadlocks by evaluating dependencies between the caller and child process.
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
The code example avoids a deadlock condition by calling p.StandardOutput.ReadToEnd before p.WaitForExit. A deadlock condition can result if the parent process calls p.WaitForExit before p.StandardOutput.ReadToEnd and the child process writes enough text to fill the redirected stream. The parent process would wait indefinitely for the child process to exit. The child process would wait indefinitely for the parent to read from the full StandardOutput stream.
There is a similar issue when you read all text from both the standard output and standard error streams. The following C# code, for example, performs a read operation on both streams.
// Do not perform a synchronous read to the end of both
// redirected streams.
// string output = p.StandardOutput.ReadToEnd();
// string error = p.StandardError.ReadToEnd();
// p.WaitForExit();
// Use asynchronous read operations on at least one of the streams.
p.BeginOutputReadLine();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();
Almost everything above taken from msdn, I suggest you read it fully to avoid creating deadlocks further.
Upvotes: 2