2014-10-15 9 views
9

मैं एक आवेदन कोडिंग कर रहा हूं और मुझे डेडलॉक में समस्या है।डेडलॉक। मानक इनपुट

मेरे कोड है कि तरह है:

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

तब मैं इस प्रक्रिया को तो मैं

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(); 
    } 
} 

उपयोग करने के लिए एक .xml फाइल भेजने के लिए है तो वास्तव में मैं का एक हिस्सा भेज सकते हैं मेरे मेरी प्रक्रिया में .xml-file लेकिन एक पल में, मुझे एक डेडलॉक मिलेगा। मुझे नहीं पता कि सही तरीके से BeginOutputReadLine() का उपयोग कैसे करें I

+0

प्रक्रिया-उदाहरण का उपयोग सीधे स्ट्रीम के रूप में करने का कोई तरीका नहीं है? जैसे 'xs.Serialize (पी। मानक इनपुट, डेटा) '? –

+0

क्या आप वाकई प्राप्त करने वाले पक्ष में डेटा पढ़ रहे हैं? यदि बफर भरने पर प्राप्त पक्ष पढ़ नहीं रहा है तो आप अवरुद्ध हो सकते हैं। क्या आपके पास प्राप्त करने वाले पक्ष के लिए कोड है? –

+0

आप डेडलॉक का सामना कैसे करते हैं? मैं पूछ रहा हूं, क्योंकि वहां 'लॉक' नहीं है - इसलिए यह पूरी तरह से स्पष्ट नहीं है, मेरे लिए, कैसे लटका होना चाहिए (जिसे डेडलॉक के रूप में वर्णित किया जा सकता है) ... –

उत्तर

1

सबसे पहले, तुम क्यों Process.StandardInput -property सीधे, का उपयोग नहीं करते अपने लक्ष्य के रूप में की तरह

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); 

अन्यथा, msdn-entry जो आप

को फिर से कर सकते हैं Process.BeginOutputReadLine() का उपयोग कर, के लिए एक स्पष्ट howto देता है
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, ... 

वैसे भी - मुझे पता है कि यह एक टिप्पणी होनी चाहिए - क्या कोई विशिष्ट कारण है कि आप अपनी प्रक्रिया को कुछ लिखने की प्रतीक्षा क्यों कर रहे हैं?

मानक आउटपुट स्ट्रीम को सिंक्रनाइज़ या असीमित रूप से पढ़ा जा सकता है। रीड, रीडलाइन, और रीडटेन्ड जैसे तरीके प्रक्रिया के आउटपुट स्ट्रीम पर सिंक्रोनस पढ़ने संचालन करते हैं। ये तुल्यकालिक पढ़ने संचालन पूर्ण नहीं होते हैं जब तक कि संबंधित प्रक्रिया मानक आउटपुट स्ट्रीम पर लिखती है, या स्ट्रीम को बंद नहीं करती है। इसके विपरीत, BeginOutputReadLine मानक आउटपुट स्ट्रीम पर एसिंक्रोनस रीड ऑपरेशंस प्रारंभ करता है। यह विधि धारा आउटपुट के लिए नामित ईवेंट हैंडलर सक्षम करती है और तुरंत कॉलर पर लौटती है, जो अन्य काम निष्पादित कर सकती है जबकि स्ट्रीम आउटपुट ईवेंट हैंडलर को निर्देशित किया जाता है।

जिसका मतलब है, कि यदि आपके प्रक्रिया कुछ भी लिखना नहीं है (और आप इंतजार कर रहे हैं), तो आपको बेहद प्रतिक्रिया के लिए कताई कर रहे हैं ...

संपादित

आप इसके अलावा एक हैंडलर जोड़ने चाहिए

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

और

तरह Process.ErrorDataReceived को 210
while (!streamReader.EndOfStream) 
{ 
    var line = streamReader.ReadLine(); 
    process.StandardInput.WriteLine(line); 

    Console.WriteLine(line); 

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

त्रुटि-मामलों को संभालने के लिए भी (जो भी हो सकता है)।

+0

कार्यक्रम मेरे लिए ऐसा नहीं है। आपके उत्तरों के साथ त्रुटियों को हल करने और अंतिम कोड भेजने का प्रयास करेगा। बहुत कुछ। –

+0

हाय, कुछ डेटा प्रिंट के बाद मुझे यह त्रुटि मिली: स्ट्रीम पर एक एसिंक रीड ऑपरेशन पहले ही शुरू हो चुका है। क्या आप जानते हैं कि मैं कैसे हल कर सकता हूं यह? था nk के। –

+0

@SteevenBrunner यह तब होता है जब आप '.ButginOutputReadLine()' को कॉल करते हैं, जिसे पहले 'ओउटपुटडेटा रिसीव' के साथ बुलाया जाता था। यही कारण है कि मैंने 'AutoResetEvent' का उपयोग किया है। आपने वास्तव में किस दृष्टिकोण की कोशिश की और आप वर्तमान में किसका उपयोग कर रहे हैं? क्या आप इस जानकारी को अपने प्रश्न में डाल सकते हैं? –

संबंधित मुद्दे