2011-03-19 15 views
6

Konsol çıkışı 'dalgalar' olarak döndüğünde sorun yaşıyorum. Örneğin, konsol her saniye bir şey çıkarır ve örneğin olay her dakika 60 kez tetiklenir (tüm olaylar aynı anda).Diğer işlem konsolu çıkışlarını okuma

Kodum:

Process Proc = new Process(); 
Proc.StartInfo.FileName = SSMS.BinaryDir + "HldsUpdateTool.exe"; 
Proc.StartInfo.Arguments = "-command update -game tf -dir " + SSMS.RootDir + Key; 
Proc.StartInfo.UseShellExecute = false; 
Proc.StartInfo.RedirectStandardOutput = true; 
Proc.StartInfo.RedirectStandardError = true; 

Proc.EnableRaisingEvents = true; 
Proc.StartInfo.CreateNoWindow = false; 

Proc.ErrorDataReceived += new DataReceivedEventHandler(Proc_ErrorDataReceived); 
Proc.OutputDataReceived += new DataReceivedEventHandler(Proc_OutputDataReceived); 
Proc.Exited += new EventHandler(Proc_Exited); 

Proc.Start(); 
Proc.BeginErrorReadLine(); 
Proc.BeginOutputReadLine(); 

ben güncelleme aracı ile sorunu olduğunu şüphelenebilir. Konsol çıkışı olan diğer programlar iyi çalışıyor.

zaman doğrultusunda

olaylar tetiklenir: (= hiçbir şey olmadı; | olayı harekete)

Should be: ==|==|==|==|==|==|== 
Is: ========|||||||=========||||||===== 
+0

Çıkışı temizlemeniz gerektiğini düşünüyorum. Nasıl yapılacağını bilmiyorum – BlackBear

cevap

6

Programın kullandığı stdout çıktı arabelleğinin etkisini görüyorsunuz. Bu, C çalışma zamanı kitaplığının standart bir özelliğidir; arabellek, konsol yerine bir boruya yazdığını algıladığında etkinleştirilir. Programdaki her printf() ifadesinden sonra otomatik olarak kızarma yerine. Tampon genellikle yaklaşık 2 kilobayttır. Ve sadece dolduktan sonra kızardı. Bu, verimliliği her geçen gün arttırır, her defasında kızarma çok fazla yük getirir. Çıktı bir dosyaya veya cihaza yazıldığında, normal yönlendirme senaryolarında önemlidir.

Bunun nereye gittiğini görebilirsiniz, gördüğünüz kümeler o arabelleğin içeriğidir. Bunun için basit bir düzeltme yoktur, programda arabelleği devre dışı bırakmak veya gerektiğinde yıkamak için ameliyat gereklidir. Bu, paranın durduğu yerde, programı değiştirirseniz bunu yapmayacaksınız. Konsolunuza, OutputDataReceived'den aldığınız şeyleri arabelleğe almayı bırakabilirsiniz, ancak bu biraz saçma olabilir.

Program, çıktıyı işleyebileceğinizden daha hızlı bir şekilde gönderirken bu efekti göremezsiniz. Hangisi oldukça yaygındır. Çıkış tamponunun boş ve hızlı bir şekilde tekrar doldurulmasını beklerken etkin bir şekilde bloke olur.

Bunun için bir açıklama daha var, OutputReceived öğesinin hangi hızda ateşleyebileceği, kaç tane iş parçacığının çalıştığına da bağlı. Bu, cpu çekirdeklerinin sayısından fazlaysa, OutputReceived çağıran tp iş parçacığı, 0,5 saniyenin katları tarafından geciktirilebilir. Ancak, yönlendirdiğiniz tüm programlarda kümelenmeyi görürsünüz.

+0

Şunlara da bakabilirsiniz: http://alabaxblog.info/2013/06/redirectstandardoutput-beginoutputreadline-pattern-broken/ – Almund

0

C# aşina hiçbir şekilde değilim ama docs arayarak bu konu ile ilgili faydalı bilgiler bulabilirsiniz'un temizlenmesi için konsolunda. Belki böyle

: (siz de Akışı Hata baskı yapıyorsanız ve Console.Error.Flush())

Console.Out.Flush() 
0

Console.Out.Flush() kullanmayı düşünün.

Anladığım kadarıyla, işleyiciler, Console.Out.Write() ile komut satırına yazmıyorlar; başka bir şeyin kullandıkları bir arabelleğe yazıyorlar. Console.Out.Write()'a yapılan birden fazla çağrıyla, tüm bufferes aynı anda yazılmaz - bazı metinler diğerlerinden daha uzun bir tamponda kalır. Console.Out.Flush(), sistemi geçerli arabelleğini hemen yazmaya zorlar.