2014-10-15 54 views
9

Bir uygulamayı kodluyorum ve kilitlenme ile ilgili bir sorun yaşıyorum.Süreç işlenirken kilitlenme.StandardInput

Benim kod böyledir:

Process p = new Process(); // That using an other application 

Sonra Yani aslında ben bir kısmını gönderebilirsiniz Bu süreçte yüzden

XmlSerializer xs = new XmlSerializer(data.GetType()); 
using (var ms = new MemoryStream()) 
{ 
    var sw = new StreamWriter(ms); 
    XmlWriter xmlwriter = XmlWriter.Create(sw, xmlWriterSettings); 
    xmlwriter.WriteProcessingInstruction("PipeConfiguratorStyleSheet", processing); 
    xs.Serialize(xmlwriter, data); 
    xmlwriter.Flush(); 
    ms.Position = 0; 
    var sr = new StreamReader(ms); 
    while (!sr.EndOfStream) 
    { 
     String line = sr.ReadLine(); 
     p.StandardInput.WriteLine(line);     
     Console.WriteLine(line); 
     p.BeginOutputReadLine(); 
     p.CancelOutputRead(); 
    } 
} 

kullanmak için bir .xml dosyası göndermek ettik benim .xml dosyası benim sürecime ama bir an, bir çıkmaz getireceğim. Doğru kullanmayı bilmiyorum BeginOutputReadLine() Sanırım.

+0

Süreç örneği doğrudan akış olarak kullanmak için bir yöntem yok mu? xs.Serialize (p.StandardInput, data) 'gibi? –

+0

Alıcı tarafın veriyi okuduğundan emin misiniz? Arabellek dolduğunda alıcı taraf okunmuyorsa engellenebilirsiniz. Alıcı taraf için kodunuz var mı? –

+0

Deadlock ile nasıl karşılaşırsınız? Ben soruyorum, çünkü "kilit" yoktur - bu yüzden tam olarak açık değil, benim için nasıl bir askıda olmalı (bir kilitlenme olarak tarif edilebilir) ... –

cevap

1

Öncelikle, neden Aksi

var process = new Process 
{ 
    // all your init stuff 
}; 
var xmlSerializer = new XmlSerializer(data.GetType()); 
var xmlwriter = XmlWriter.Create(process.StandardInput, xmlWriterSettings); 
xmlSerializer.Serialize(xmlwriter, data); 

gibi, hedef olarak doğrudan Process.StandardInput -property kullanmayın, msdn-entry sen

için pişmanlık olabilir, Process.BeginOutputReadLine() kullanmak için net bir howto verir
var autoResetEvent = new AutoResetEvent(false); // this mutex acts as our bouncer for the reading-part 
var process = new Process 
{ 
    // all your init stuff 
}; 
process.StartInfo.UseShellExecute = false; 
process.StartInfo.RedirectStandardOutput = true; 
process.OutputDataReceived += (sender, args) => { 
    // TODO you could read the content here with args.Data 
    autoResetEvent.Set(); 
}; 
process.Start(); 

using (var memoryStream = new MemoryStream()) 
{ 
    using (var streamWriter = new StreamWriter(memoryStream)) 
    { 
     var xmlSerializer = new XmlSerializer(data.GetType()); 
     var xmlwriter = XmlWriter.Create(streamWriter, xmlWriterSettings); 
     xmlSerializer.Serialize(xmlwriter, data); 
    } 
    memoryStream.Position = 0; 
    using (var streamReader = new StreamReader(memoryStream)) 
    { 
     while (!streamReader.EndOfStream) 
     { 
      var line = streamReader.ReadLine(); 
      process.StandardInput.WriteLine(line); 

      Console.WriteLine(line); 

      process.BeginOutputReadLine(); 
      autoResetEvent.WaitOne(); 
     } 
    } 
} 

// TODO closing the process.StandardInput, exiting process, ... 

Neyse - Bunun bir yorum olması gerektiğini biliyorum - sürecinizin bir şeyler yazmasını beklemenizin belirli bir nedeni var mı?

StandardOutput akışı eşzamanlı veya zaman uyumsuz olarak okunabilir. Okuma, ReadLine ve ReadToEnd gibi yöntemler, işlemin çıkış akışında senkronize okuma işlemleri gerçekleştirin. Bu senkronize okuma işlemleri, ilişkili Süreç StandardOutput akışına yazana kadar tamamlanmaz veya akışı kapatır. Buna karşılık, BeginOutputReadLine, StandardOutput akışında asenkron okuma işlemlerini başlatır. Bu yöntem, akım çıkışı için belirlenmiş bir olay işleyici 'u etkinleştirir ve derhal akım çıkışı eylemciye yönlendirilirken başka bir iş gerçekleştirebilen arayan kişiye geri döner. sürecinizle şey yazmaz (ve bekliyor), sen sonsuz yanıt dönmekte olduğu anlamına gelir

...

DÜZENLEME

Siz ayrıca bir işleyici eklemek gerekir

process.StartInfo.RedirectStandardError = true; 
process.ErrorDataReceived += (sender, args) => { 
    // TODO do something with the response of args.Data 
    autoResetEvent.Set(); 
}; 

ve

gibi Process.ErrorDataReceived için Hata durumlarını da ele almak için (bu ne anlama gelebilir) 210
while (!streamReader.EndOfStream) 
{ 
    var line = streamReader.ReadLine(); 
    process.StandardInput.WriteLine(line); 

    Console.WriteLine(line); 

    process.BeginOutputReadLine(); 
    process.BeginErrorReadLine(); 
    autoResetEvent.WaitOne(); 
} 

.

+0

Program benim için böyle çalışmıyor. Cevapları ile hatalarını çözmek ve son kodu göndermek için çalışacağız.Çok fazla veri –

+0

Merhaba, bazı veri yazdırma sonra bu hatayı aldım: Bir async okuma işlemi zaten akışında başlatıldı.Bunu nasıl çözebilirim bu mu? nk en. –

+0

@SteevenBrunner Bu, '.OutputDataReceived' ile daha önce çağırılmadan' .BeginOutputReadLine() 'adını verdiğinizde olur. Bu yüzden AutoResetEvent kullanıyorum. Hangi yaklaşımı gerçekten denediniz ve şu anda kullanıyorsunuz? Bu bilgiyi sorunuza uygun bir şekilde koyabilir misiniz? –