Tôi đang làm việc với C# và gặp sự cố khi hiểu cách đọc stdout không đồng bộ từ quá trình con. Những gì tôi muốn làm là tạo ra một tiến trình con thực hiện một ứng dụng và sau đó trình bày bất cứ điều gì được nhận từ quá trình đó 'stdout trong một hộp văn bản. Tôi cần phải xem mọi nhân vật đầu ra từ tiến trình con ngay lập tức và không thể chờ đợi một dòng để hoàn thành, do đó tôi không nghĩ rằng sự kiện Process.OutputDataReceived
phù hợp với mục đích của tôi. Bạn có thể cho tôi biết một cách lành mạnh để thực hiện điều này không?C# Đọc stdout của quá trình con không đồng bộ
Tôi đã thử gọi Process.StandardOutput.BaseStream.BeginRead()
và chuyển chức năng gọi lại cho nó, nhưng trong chức năng gọi lại này, tôi nhận được ngoại lệ từ Process.StandardOutput.BaseStream.EndRead()
.
Mã của tôi trông như thế này (quá trình con là công cụ tập lệnh - viết tắt là "SE" - để xác minh chức năng của thiết bị bên ngoài. Kịch bản được thực thi theo thứ tự và mỗi tập lệnh yêu cầu một phiên bản của ứng dụng SE)
private bool startScript()
{
// Starts the currently indexed script
if (null != scriptList)
{
if (0 == scriptList.Count || scriptListIndexer == scriptList.Count)
{
// If indexer equals list count then there are no active scripts in
// the list or the last active script in the list has just finished
return false; // ## RETURN ##
}
if (ScriptExecutionState.RUNNING == scriptList[scriptListIndexer].executionState)
{
return false; // ## RETURN ##
}
if (0 == SE_Path.Length)
{
return false; // ## RETURN ##
}
SE_Process = new Process();
SE_Process.StartInfo.FileName = SE_Path;
SE_Process.StartInfo.CreateNoWindow = true;
SE_Process.StartInfo.UseShellExecute = false;
SE_Process.StartInfo.RedirectStandardError = true;
SE_Process.StartInfo.RedirectStandardOutput = true;
SE_Process.EnableRaisingEvents = true;
SE_Process.StartInfo.Arguments = scriptList[scriptListIndexer].getParameterString();
// Subscribe to process exit event
SE_Process.Exited += new EventHandler(SE_Process_Exited);
try
{
if (SE_Process.Start())
{
// Do stuff
}
else
{
// Do stuff
}
}
catch (Exception exc)
{
// Do stuff
}
// Assign 'read_SE_StdOut()' as call-back for the event of stdout-data from SE
SE_Process.StandardOutput.BaseStream.BeginRead(SE_StdOutBuffer, 0, SE_BUFFERSIZE, read_SE_StdOut, null);
return true; // ## RETURN ##
}
else
{
return false; // ## RETURN ##
}
}
private void read_SE_StdOut(IAsyncResult result)
{
try
{
int bytesRead = SE_Process.StandardOutput.BaseStream.EndRead(result); // <-- Throws exceptions
if (0 != bytesRead)
{
// Write the received data in output textbox
...
}
// Reset the callback
SE_Process.StandardOutput.BaseStream.BeginRead(SE_StdOutBuffer, 0, SE_BUFFERSIZE, read_SE_StdOut, null);
}
catch (Exception exc)
{
// Do stuff
}
}
void SE_Process_Exited(object sender, EventArgs e)
{
// Keep track of whether or not the next script shall be started
bool continueSession = false;
switch (SE_Process.ExitCode)
{
case 0: // PASS
{
// Do stuff
}
...
}
SE_Process.Dispose(); // TODO: Is it necessary to dispose of the process?
if (continueSession)
{
ts_incrementScriptListIndexer();
if (scriptListIndexer == scriptList.Count)
{
// Last script has finished, reset the indexer and re-enable
// 'scriptListView'
...
}
else
{
if (!startScript())
{
// Do stuff
}
}
}
else
{
ts_resetScriptListIndexer();
threadSafeEnableScriptListView();
}
}
Điều gì xảy ra sau một quá trình SE thúc tôi nhận được một ngoại lệ kiểu InvalidOperationException
nói rằng
StandardOut chưa được chuyển hướng hoặc quá trình này đã chưa bắt đầu.
từ cuộc gọi đến SE_Process.StandardOutput.BaseStream.EndRead()
. Tôi không hiểu tại sao vì tôi đã đặt SE_Process.StartInfo.RedirectStandardOutput
trước khi bắt đầu mọi quy trình mới. Nó xuất hiện với tôi như thể các dòng stdout của một quá trình thoát gọi hàm read_SE_StdOut()
của tôi sau khi quá trình đã được xử lý, là có thể?
Cảm ơn bạn đã đọc!
Bạn có thể quan tâm đến thư viện [MedallionShell] (https://github.com/madelson/MedallionShell), đơn giản hóa việc xử lý luồng io quy trình, đặc biệt là các hoạt động không đồng bộ – ChaseMedallion