如何在使用IPC C#时从管道流中有效读取

时间:2016-01-22 23:03:18

标签: c# stream ipc named-pipes

我在下面编写了我的程序的简化版本。流程A启动子流程(流程B)。我使用匿名管道来编写有关在进程B上运行的方法的进度的信息。同时,我在进程A中有一个函数,它不断地从流中读取以查看是否有来自管道的新更新。如果有,则更新流程A上的表单以反映进度。这可以按预期工作,但我想知道是否有更好的方法来实现这一点,而不必不断检查流,看看是否有任何新的进展更新。

/////////////////
///Process A ////
/////////////////

public void LaunchProcessB()
{
    using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.In,
            HandleInheritability.Inheritable))
    {
        var _Process = new Process();
        _Process.StartInfo.FileName = exeString;
        _Process.StartInfo.Arguments = pipeServer.GetClientHandleAsString()
        _Process.StartInfo.RedirectStandardOutput = true;
        _Process.StartInfo.RedirectStandardInput = true;
        _Process.StartInfo.CreateNoWindow = true;
        _Process.StartInfo.UseShellExecute = false;
        _Process.Start(); //launches process B

        pipeServer.DisposeLocalCopyOfClientHandle();

        using (StreamReader sr = new StreamReader(pipeServer))
        {
            try
            {
                while (true)
                {
                    string temp = sr.ReadLine();
                    if (temp == null) break;

                    int result;
                    if (Int32.TryParse(temp, out result))
                        ShowDocumentProgress(result);
                    else ShowProgress(temp);
                }
            }
            catch (Exception)
            {
                //error occured when reading from stream.
            }
        }

        if (!_Process.Responding && !_Process.HasExited)
        {
            _Process.Kill();
            return;
        }

        _Process.WaitForExit(10000);
    }
}

private void ShowProgressPercent(int percentage)
{
    if (percentage > currentPercentage)
    {
        progressBar.Value = percentage;
    }
}

private void ShowProgress(string progressString)
{
    labelMessage.Text = progressString;
}


/////////////////
///Process B ////
/////////////////

private StreamWriter _progressWriter;
private PipeStream _progressPipe;

static int Main(string[] args)
{
    using (progressPipe = new AnonymousPipeClientStream(PipeDirection.Out, args[0]))
    using (_progressWriter = new StreamWriter(_progressPipe))   
    {
        RunLongProcess()
    }
}

private void RunLongProcess() 
{
    //attaches events to PercentProgress and StageProgress methods.  
}

private void PercentProgress(int percentage)
{
    _progressWriter.WriteLine(percentage.ToString());
    _progressPipe.WaitForPipeDrain();
}

private void StageProgress(string stage) 
{
    _progressWriter.WriteLine(stage);
    _progressPipe.WaitForPipeDrain();
}

1 个答案:

答案 0 :(得分:2)

没有必要使用while条件。只需阅读,直到temp为空。这是流的结束信号。

将其设为while(true)循环。

我认为您还需要添加异常处理以捕获终止和切断管道的进程。 !_Process.HasExited && pipeServer.IsConnected是不够的,因为它可能是真的,但在测试后立即切换为假。

我还会在最后添加一个WaitForExit,以确保在继续之前系统已停顿。