Note that there are some explanatory texts on larger screens.

plurals
  1. POParse output from a process that updates a single console line
    primarykey
    data
    text
    <p>Greetings stackoverflow members,</p> <p>in a BackgroundWorker of a WPF Frontend i run <a href="http://sox.sourceforge.net/" rel="nofollow">sox</a> (open source console sound processing tool) in a <code>System.Diagnostics.Process</code>. In that same way i use several other command line tools and parse their output to poulate progress bars in my frontend.</p> <p>This works fine for the other tools but not for Sox since instead of spamming new lines for each progress step, it updates a single line on the console by only using carriage returns (\r) and no line feeds (\n). I tried both asynchronous and synchronous reads on <code>process.StandardError</code>.</p> <p>Using async <code>process.ErrorDataReceived += (sender, args) =&gt; FadeAudioOutputHandler(clip, args);</code> in combination with <code>process.BeginErrorReadLine();</code> doesn't produce any individual status updates because for some reason the carriage returns do not trigger ReadLine, even though the <a href="http://msdn.microsoft.com/en-us/library/system.io.streamreader.readline%28v=VS.100%29.aspx" rel="nofollow">MSDN docs</a> suggest that it should. The output is spit out in one chunk when the process finishes.</p> <p>I then tried the following code for synchronous char by char reads on the stream:</p> <pre><code>char[] c; var line = new StringBuilder(); while (process.StandardError.Peek() &gt; -1) { c = new char[1]; process.StandardError.Read(c, 0, c.Length); if (c[0] == '\r') { var percentage = 0; var regex = new Regex(@"%\s([^\s]+)"); var match = regex.Match(line.ToString()); if (match.Success) { myProgressObject.ProgressType = ProgressType.FadingAudio //... some calculations omitted for brevity percentage = (int) Math.Round(result); } else { myProgressObject.ProgressType = ProgressType.UndefinedStep; } _backGroundWorker.ReportProgress(percentage, myProgressObject); line.Clear(); } else { line.Append(c[0]); } } </code></pre> <p>The above code does not seem to read the stream in realtime but will stall output for a while. Then it spams a small chunk and finally deadlocks half-way through the process.</p> <p>Any hints towards the right direction would be greatly appreciated!</p> <p><strong>UPDATE with (sloppy?) solution:</strong></p> <p>This drove me crazy because nothing i tried on the C# side of things seemed to have any effect on the results. My original implementation, before changing it 15 times and introducing new dependencies, was fine.</p> <p>The problem is with sox and RedirectStandardError alone. I discovered that after grabbing the sox source code and building my own version. First i removed all output of sox entirely except for the stuff i was really interested in and then changing the output to full lines followed by a newline <code>\n</code> . I assumed that this would fix my issues. Well, it didn't. I do not know enough c++ to actually find out why, but they seem to have tempered with how stdio writes to that stream, how it's buffered or do it in such a special way that the streamreader on the c# side is not flushed until the default 4096 byte buffer is full. I confirmed that by padding each line to at least 4096 byte. So in conclusion all i had to do was to manually flush stderr in sox.c after each <code>fprintf(stderr, ...)</code> call in <code>display_status(...)</code>:</p> <pre><code>fflush(stderr); </code></pre> <p>Though, I'm not sure this is anywhere close to an elegant solution.</p> <p>Thanks to Erik Dietrich for his answer which made me look at this from a different angle.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload