2010-12-15 13 views
6

मुझे कंसोल आउटपुट को विंडोज़ फॉर्म टेक्स्ट बॉक्स में रीडायरेक्ट करने में समस्या हो रही है। समस्या धागा से संबंधित है। मैं निम्नलिखित तरीके सेमैं कंसोल प्रोग्राम के आउटपुट को थ्रेड सुरक्षित तरीके से टेक्स्ट बॉक्स में रीडायरेक्ट कैसे करूं?

private void RunConsoleApp() 
{ 
    Process proc = new Process(); 
    proc.StartInfo.FileName = "app.exe"; 
    proc.StartInfo.Arguments = "-a -b -c"; 
    proc.StartInfo.UseShellExecute = false; 

    // set up output redirection 
    proc.StartInfo.RedirectStandardOutput = true; 
    proc.StartInfo.RedirectStandardError = true;  
    proc.EnableRaisingEvents = true; 
    proc.StartInfo.CreateNoWindow = true; 

    // Set the data received handlers 
    proc.ErrorDataReceived += proc_DataReceived; 
    proc.OutputDataReceived += proc_DataReceived; 

    proc.Start(); 
    proc.BeginErrorReadLine(); 
    proc.BeginOutputReadLine(); 
    proc.WaitForExit(); 

    if (proc.ExitCode == 0) 
    { 
     out_txtbx.AppendText("Success." + Environment.NewLine); 
    } 
    else 
    { 
     out_txtbx.AppendText("Failed." + Environment.NewLine); 
    } 
} 

एक कंसोल अनुप्रयोग चला रहा हूँ, और फिर कब्जा और इस उत्पादन हैंडलर के साथ डेटा की प्रक्रिया,

// Handle the date received by the console process 
void proc_DataReceived(object sender, DataReceivedEventArgs e) 
{ 
    if (e.Data != null) 
    { 
     if ((e.Data.EndsWith("DONE.")) || (e.Data.EndsWith("FAILED.")) || 
      (e.Data.StartsWith("RESET"))) 
     { 
      // This crashes the application, but is supposedly the correct method 
      this.AppendText(e.Data + Environment.NewLine); 

      // This works, but the debugger keeps warning me that the call 
      // is not thread safe 
      //out_txtbx.AppendText(e.Data + Environment.NewLine); 
     } 
    } 
} 

सांत्वना पाठ तो इस तरह जोड़ दिया जाता है,

delegate void AppendTextDelegate(string text); 

// Thread-safe method of appending text to the console box 
private void AppendText(string text) 
{ 
    // Use a delegate if called from a different thread, 
    // else just append the text directly 
    if (this.out_txtbx.InvokeRequired) 
    { 
     // Application crashes when this line is executed 
     out_txtbx.Invoke(new AppendTextDelegate(this.AppendText), new object[] { text }); 
    } 
    else 
    { 
     this.out_txtbx.AppendText(text); 
    } 
} 

सभी दस्तावेज और उदाहरणों से मैंने देखा है कि यह सही तरीका प्रतीत होता है, सिवाय इसके कि जब यह out_txtbx.Invoke कहा जाता है तो यह एप्लिकेशन को क्रैश कर रहा है।

क्या टूटा जा सकता है और ऐसा करने के लिए वैकल्पिक तरीके क्या हैं?


समाधान (के रूप में हंस Passant से कहा)

समस्या यह है कि अनुप्रयोग एक "घातक आलिंगन" में फंस गया है लाइन की वजह से है,

proc.WaitForExit(); 

उस रेखा को हटा दिया जाना चाहिए और विधि इस तरह दिखनी चाहिए,

private void RunConsoleApp() 
{ 
    Process proc = new Process(); 
    proc.StartInfo.FileName = "app.exe"; 
    proc.StartInfo.Arguments = "-a -b -c"; 
    proc.StartInfo.UseShellExecute = false; 

    // set up output redirection 
    proc.StartInfo.RedirectStandardOutput = true; 
    proc.StartInfo.RedirectStandardError = true;  
    proc.EnableRaisingEvents = true; 
    proc.StartInfo.CreateNoWindow = true; 

    // Set the data received handlers 
    proc.ErrorDataReceived += proc_DataReceived; 
    proc.OutputDataReceived += proc_DataReceived; 

    // Configure the process exited event 
    proc.Exited += new EventHandler(ProcExited); 

    proc.Start(); 
    proc.BeginErrorReadLine(); 
    proc.BeginOutputReadLine(); 

    // This blocks the main thread and results in "deadly embrace" 
    // The Process.Exited event should be used to avoid this. 
    //proc.WaitForExit(); 
} 

और एक ईवेंट हैंडलर प्रदान की जानी चाहिए,

/// <summary> 
/// Actions to take when console process completes 
/// </summary> 
private void ProcExited(object sender, System.EventArgs e) 
{ 
    Process proc = (Process)sender; 

    // Wait a short while to allow all console output to be processed and appended 
    // before appending the success/fail message. 
    Thread.Sleep(40); 

    if (proc.ExitCode == 0) 
    { 
     this.AppendText("Success." + Environment.NewLine); 
     ExitBootloader(); 
    } 
    else 
    { 
     this.AppendText("Failed." + Environment.NewLine); 
    } 

    proc.Close(); 
} 
+2

आपको क्या त्रुटि मिलती है? – SLaks

+0

और किस लाइन पर ?? – decyclone

+0

मैंने बिना त्रुटि के यह किया है। यदि उस समय तक पर्याप्त उत्तर नहीं है, तो मैं अपने कोड नमूने में जा सकता हूं, मैं पोस्ट करूंगा। ध्यान दें कि जब मैं घर आऊंगा तो यह शाम बाद में होगा। मैंने एक टेक्स्टवाइटर ऑब्जेक्ट बनाया था जो एक टेक्स्टबॉक्स को लिखा था, फिर कंसोल को निर्देशित किया। TextOriter को सेट करें। Http://msdn.microsoft.com/en-us/library/system.console.setout%28v=VS.90%29.aspx – IAbstract

उत्तर

9
proc.WaitForExit(); 

यह गतिरोध कहा जाता है की कोशिश करो। आपका मुख्य धागा अवरुद्ध है, प्रक्रिया से बाहर निकलने की प्रतीक्षा कर रहा है। यह आवश्यक कर्तव्यों की देखभाल करने से रोकता है। यूआई को अद्यतन रखने की तरह। और यह सुनिश्चित कर लें कि Control.Invoke() अनुरोध प्रेषित किए गए हैं। यह AppendText() विधि को पूरा करने से रोकता है। जो बाहर निकलने की प्रक्रिया को रोकता है। जो आपके UI थ्रेड को WaitForExit() कॉल से पहले कभी भी रोकता है। "घातक गले लगाओ", उर्फ ​​डेडलॉक।

आप अपने मुख्य धागे को अवरुद्ध नहीं कर सकते हैं। इसके बजाय Process.Exited घटना का उपयोग करें।

+0

धन्यवाद हंस, जो सही समझ में आता है (अब आपने इसे समझाया है)। –

0

out_txtbx.Invoke(new AppendTextDelegate(this.AppendText), text); 
+1

यह काम नहीं करता –

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

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