2010-04-06 10 views
68

एक कंसोल एप्लिकेशन पर विचार करें जो कुछ अलग-अलग थ्रेड में कुछ सेवाएं शुरू करता है। इसे करने की आवश्यकता है कि उपयोगकर्ता को इसे बंद करने के लिए Ctrl + C दबाएं।.NET कंसोल ऐप कैसे चलाना है?

इनमें से कौन सा बेहतर तरीका है?

static ManualResetEvent _quitEvent = new ManualResetEvent(false); 

static void Main() { 
    Console.CancelKeyPress += (sender, eArgs) => { 
     _quitEvent.Set(); 
     eArgs.Cancel = true; 
    }; 

    // kick off asynchronous stuff 

    _quitEvent.WaitOne(); 

    // cleanup/shutdown and quit 
} 

या यह, Thread.Sleep (1) का उपयोग करते हुए:

static bool _quitFlag = false; 

static void Main() { 
    Console.CancelKeyPress += delegate { 
     _quitFlag = true; 
    }; 

    // kick off asynchronous stuff 

    while (!_quitFlag) { 
     Thread.Sleep(1); 
    } 

    // cleanup/shutdown and quit 
} 

उत्तर

41

आप हमेशा विशेष रूप से जब आप चर पुनः जाँच करने के लिए कोड के लिए मजबूर कर रहे हैं, जबकि छोरों का उपयोग कर रोकना चाहते हैं,। यह सीपीयू संसाधनों को बर्बाद करता है और आपके प्रोग्राम को धीमा कर देता है।

मैं निश्चित रूप से पहला कहूंगा।

+2

+1। इसके अलावा, चूंकि 'बूल' को 'अस्थिर' के रूप में घोषित नहीं किया गया है, इसलिए निश्चित संभावना है कि 'लूप' में '_quitFlag' को पढ़ा जाएगा, जबकि लूप को अनुकूलित किया जाएगा, जिससे अनंत लूप हो जाएगा। –

20

वैकल्पिक रूप से, एक और अधिक सरल उपाय सिर्फ यह है:

Console.ReadLine(); 
+0

मैं यह सुझाव देने वाला था, लेकिन यह केवल Ctrl-C –

+0

पर नहीं रुक जाएगा, मुझे यह धारणा मिली है कि CTRL-C केवल एक उदाहरण था - – Cocowalla

+0

को बंद करने के लिए कोई भी उपयोगकर्ता इनपुट याद रखें कि 'Console.ReadLine()' है धागा अवरुद्धतो एप्लिकेशन अभी भी चल रहा है लेकिन उपयोगकर्ता को – fabriciorissetto

2
दो पहले एक के

बेहतर

_quitEvent.WaitOne(); 

है, क्योंकि एक दूसरे में धागा जाग हर एक मिलीसेकंड में बदल गया हो जाएगी ओएस इंटरप्ट जो महंगा है

+0

में पूर्ण कोड निष्पादित न करें, यह 'कंसोल' विधियों के लिए एक अच्छा विकल्प है यदि आप कंसोल संलग्न नहीं है (क्योंकि, उदाहरण के लिए, प्रोग्राम एक सेवा द्वारा शुरू किया जाता है) –

11

आप ऐसा कर सकते हैं (और CancelKeyPress ईवेंट हैंडलर को हटाएं):

while(!_quitFlag) 
{ 
    var keyInfo = Console.ReadKey(); 
    _quitFlag = keyInfo.Key == ConsoleKey.C 
      && keyInfo.Modifiers == ConsoleModifiers.Control; 
} 

यह सुनिश्चित नहीं है कि यह बेहतर है, लेकिन मुझे लूप में Thread.Sleep पर कॉल करने का विचार पसंद नहीं है .. मुझे लगता है कि यह उपयोगकर्ता इनपुट पर अवरुद्ध करने के लिए क्लीनर है।

+0

मुझे यह पसंद नहीं है कि आप Ctrl + C द्वारा सिग्नल किए गए सिग्नल के बजाय Ctrl + C कुंजी की जांच कर रहे हैं। – CodesInChaos

0

आपको ऐसा करना चाहिए जैसे आप विंडोज़ सेवा प्रोग्रामिंग कर रहे हों। आप कभी भी एक वक्तव्य का उपयोग नहीं करेंगे बल्कि आप एक प्रतिनिधि का उपयोग करेंगे। WaitOne() आमतौर पर थ्रेड्स को निपटाने के लिए इंतजार करते समय उपयोग किया जाता है - थ्रेड। नींद() - सलाह नहीं दी जाती है - क्या आपने सिस्टम टिमर्स का उपयोग करने के बारे में सोचा है। उस घटना का उपयोग करके शटर डाउन इवेंट की जांच करने के लिए?

3

ऐसा लगता है कि आप इसे जितना कठिन बना रहे हैं उतना कठिन बना रहे हैं। क्यों न केवल Join धागे को रोकने के लिए संकेत दिया है?

class Program 
{ 
    static void Main(string[] args) 
    { 
     Worker worker = new Worker(); 
     Thread t = new Thread(worker.DoWork); 
     t.IsBackground = true; 
     t.Start(); 

     while (true) 
     { 
      var keyInfo = Console.ReadKey(); 
      if (keyInfo.Key == ConsoleKey.C && keyInfo.Modifiers == ConsoleModifiers.Control) 
      { 
       worker.KeepGoing = false; 
       break; 
      } 
     } 
     t.Join(); 
    } 
} 

class Worker 
{ 
    public bool KeepGoing { get; set; } 

    public Worker() 
    { 
     KeepGoing = true; 
    } 

    public void DoWork() 
    { 
     while (KeepGoing) 
     { 
      Console.WriteLine("Ding"); 
      Thread.Sleep(200); 
     } 
    } 
} 
+2

मेरे मामले में मैं उन धागे को नियंत्रित नहीं करता जो अतुल्यकालिक चीजें चलती हैं। – intoOrbit

+0

1) मुझे यह पसंद नहीं है कि आप Ctrl + C द्वारा सिग्नल किए गए सिग्नल के बजाय Ctrl + C कुंजी की जांच कर रहे हैं। 2) यदि आपका कार्य एक कार्यकर्ता थ्रेड के बजाय कार्य का उपयोग करता है तो आपका दृष्टिकोण काम नहीं करता है। – CodesInChaos

8

मैं डॉक्स से Application.Run

static void Main(string[] args) { 

    //Do your stuff here 

    System.Windows.Forms.Application.Run(); 

    //Cleanup/Before Quit 
} 

उपयोग करने को प्राथमिकता:

वर्तमान धागे पर एक मानक आवेदन संदेश पाश चलना शुरू होता है, एक फार्म के बिना।

+5

लेकिन फिर आप इसके लिए विंडोज़ फॉर्मों पर निर्भरता लेते हैं। परंपरागत .NET ढांचे के साथ बहुत अधिक समस्या नहीं है, लेकिन वर्तमान प्रवृत्ति मॉड्यूलर तैनाती की दिशा में है जिसमें केवल आवश्यक भागों को शामिल किया गया है। – CodesInChaos

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