2010-05-28 14 views
6

पृष्ठभूमि का एक छोटा सा हिस्सा: मेरे पास एक WPF एप्लिकेशन है, जो विरासत Win32-application के लिए एक जीयूआई-फ्रंट-एंड है। विरासत ऐप एक अलग थ्रेड में डीएलएल के रूप में चलता है। यूआई में उपयोगकर्ता द्वारा चुने गए आदेशों को उस "विरासत धागे" पर बुलाया जाता है।Application.Current.Shutdown() बनाम आवेदन। वर्तमान। डिस्पैचर। बेजिन इनवोकशूटडाउन()

यदि "विरासत धागा" खत्म हो जाता है, तो जीयूआई-फ्रंट एंड अब कुछ भी उपयोगी नहीं कर सकता है, इसलिए मुझे WPF-application को बंद करने की आवश्यकता है। इसलिए, थ्रेड की विधि के अंत में, मैं Application.Current.Shutdown() पर कॉल करता हूं।

चूंकि मैं मुख्य धागे पर नहीं हूं, इसलिए मुझे इस आदेश को आमंत्रित करने की आवश्यकता है। हालांकि, मैंने देखा कि प्रेषक को बंद करने के लिए डिस्पैचर में BeginInvokeShutdown() भी है। तो मेरे सवाल है: क्या

Application.Current.Shutdown(); 

लागू और बुला बीच का अंतर है

Application.Current.Dispatcher.BeginInvokeShutdown(); 

उत्तर

7

मैं कुछ और परीक्षण किया था, और अब मुझे लगता है कि मैं मतभेद पता:

1) के रूप में, MSDN पेज, BeginInvokeShutdown में कहा गया है डिस्पैचर को बंद करने के अलावा, यह भी साफ करता है/इसके कतार aborts। Shutdown पहले डिस्पैचर कतार में सभी आइटम को संभालता है।

शटडाउन प्रक्रिया शुरू होने के बाद, कतार में सभी लंबित कार्य आइटम निरस्त हो जाते हैं।

2) एक आवेदन में मैं Application.Exit ईवेंट को संभाल सकता हूं। जब मैं शटडाउन कहता हूं तो यह घटना निकाल दी जाती है, लेकिन जब मैं BeginInvokeShutdown को कॉल करता हूं तो निकाल दिया नहीं जाता है! यह Window.Closing और Window.Closed पर लागू होता है।

समानता के लिए, दोनों मामलों में मुख्य धागा बाहर निकल गया है। अन्य चलने वाले धागे के आधार पर, यह प्रक्रिया को बंद कर देता है: प्रक्रिया से बाहर होने से पहले गैर-पृष्ठभूमि धागे पूरा होने के लिए चलाए जाते हैं।

नीचे मेरा टेस्ट कोड है। एक या Application_Startup में अन्य विधि कॉल टिप्पणी:

public partial class App 
{ 
    private void Application_Exit(object sender, ExitEventArgs e) 
    { 
     MessageBox.Show("Exiting"); 
    } 

    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     var testThread = new Thread(
      () => 
      { 
       Thread.Sleep(2000); 
       Application.Current.Dispatcher.BeginInvokeShutdown(System.Windows.Threading.DispatcherPriority.Send); 
       //Application.Current.Dispatcher.BeginInvoke(new Action(() => Application.Current.Shutdown())); 
      }); 
     testThread.Start(); 
    } 
} 

public partial class Window1 
{ 
    public Window1() 
    { 
     this.InitializeComponent(); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("One"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Two"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Three"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Four"); 
     })); 
    } 

    private void Window_Closed(object sender, EventArgs e) 
    { 
     Console.WriteLine("Closed"); 
    } 

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     Console.WriteLine("Closing"); 
    } 
} 
1

MSDN page for Shutdown()
MSDN page for BeginInvokeShutdown()

ऐसा लगता है कि यह सिर्फ शब्दावली का एक टक्कर है। BeginInvokeShutdown उस प्रेषक को बंद कर देता है, आपका आवेदन सिद्धांत में बाद में जारी रह सकता है (हालांकि एक प्रेषक के बिना, यह बहुत सीमित होगा)। Shutdown हालांकि वास्तव में आपके आवेदन से बाहर निकलता है, जो आप चाहते हैं।

+0

ठीक है, यह सटीक रूप से प्रश्न है जिसका दस्तावेज़ीकरण में उत्तर नहीं दिया गया है: क्या एप्लिकेशन के प्रेषक को बंद करना एप्लिकेशन को बंद कर देता है? –

+0

मैंने इसके लिए एक सरल WPF परीक्षण अनुप्रयोग बनाया। अपने कोड को अनुकरण करने के लिए, मैंने किया: 'थ्रेड टी = नया थ्रेड (नया थ्रेडस्टार्ट (प्रतिनिधि() {थ्रेड स्लीप (50000);}); t.Start(); Application.Current.Dispatcher .BginginInvokeShutdown (System.Windows.Threading.DispatcherPriority.Normal); '। डिस्पैचर शट डाउन ने अपने मालिक थ्रेड को मार दिया और खिड़की बंद कर दी, लेकिन पृष्ठभूमि थ्रेड को मार नहीं दिया *। – JustABill

+0

दो छोटे मतभेद: 1) मैं दूसरे धागे में शट डाउन कॉल करता हूं (हालांकि परीक्षण के माध्यम से मैं देख सकता हूं कि इससे कोई फर्क नहीं पड़ता)। 2) मेरे पास पृष्ठभूमि थ्रेड (IsBackground = true) के रूप में दूसरा थ्रेड सेट है। इस तरह, मुख्य धागा छोड़ देता है, तो यह भी मार जाता है। –

0

वैसे, डैनियल - हमारे आवेदन एक ही तरह से बनाया गया है - एक Win32 COM (डेल्फी) आवेदन करने के लिए WPF सामने के अंत अलग से चल रहा है। बात करना और हमारे दृष्टिकोण की तुलना करना दिलचस्प होगा।

लेकिन मैंने आपके प्रश्न पर क्यों ठोकर खाई है कि हमारा आवेदन डिस्पैचर.बिनिन इनवोकशूटडाउन को कॉल करने के लिए प्रयोग किया जाता है, जो कुछ मामलों के अपवाद के साथ ठीक काम करता है जहां यह ठीक से समाप्त नहीं हुआ था। जब मुझे आखिरकार एक मशीन पर हाथ मिला, जिस पर यह पुन: उत्पन्न हुआ था, तो एप्लिकेशन पर स्विच कर रहा था। Current.Shutdown() ने समस्या को ठीक किया। मुझे अभी भी समझ में नहीं आता कि समस्या क्या थी।

+0

मुझे लगता है कि ऐसा इसलिए है क्योंकि Dispatcher को कॉल करें। BginginInvokeShutdown() किसी लंबित संदेशों को बंद/साफ़ करता है। मेरे मामले में, मैं विंडो में क्लीनअप का एक गुच्छा भी करता हूं। बंद/बंद मामलों और एप्लिकेशन। एक्सिट (Win32 भाग को बंद करने के लिए)। –