2010-03-08 8 views
7

मैं एक Windows सेवा Thread.Sleep() साथ कुछ समस्याएं हो रही है कि तो मैं लगा बजाय के रूप में इस सवाल सिफारिश की गई है मैं एक टाइमर का उपयोग करने की कोशिश करेंगे पर काम कर रहा हूँ:थ्रेड नींद और Windows सेवा

Using Thread.Sleep() in a Windows Service

बात यह है है पूरी तरह से मुझे स्पष्ट नहीं है कि कोई इसे कैसे कार्यान्वित कर सकता है। VB.Net का उपयोग करने से

'' Inside The Service Object 
Dim closingGate As System.Threading.AutoResetEvent 

Protected Overrides Sub OnStart(ByVal args() As String) 
    Dim worker As New Threading.Thread(AddressOf Work) 
    worker.Start() 
End Sub 

Protected Sub Work() 
    Dim Program = New MyProgram() 
    closingGate = New System.Threading.AutoResetEvent(False) 
    Program.RunService(closingGate) 
End Sub 

Protected Overrides Sub OnStop() 
    closingGate.Set() 
End Sub 

'' Inside My Programs Code: 
Public Sub RunService(closingGate As AutoResetEvent) 
    Dim tmr As New Timer 
    '' ...and so on 

    closingGate.WaitOne() 
End Sub 

एक तरफ (मज़ाक है, लेकिन मैं सी # अगर मैं कर सकता का उपयोग किया था।) मैं सही रास्ते यहाँ पर हूँ: मेरा मानना ​​है कि इस तरह से है, लेकिन मैं सिर्फ यह सुनिश्चित करना चाहते थे? क्या यह Thread.Sleep() का उपयोग करने से बेहतर है?

+0

आपके चर के नाम कैपिटलकृत क्यों हैं? –

+0

वहां। ठीक कर दिया। –

उत्तर

19

ईमानदारी से, मुझे यह कहना होगा कि मुझे लगता है कि आप यहां पीटा पथ से थोड़ा दूर हैं।

सबसे पहले, वास्तविक कोड तैनात वास्तव में मतलब नहीं है; कार्यकर्ता थ्रेड सिग्नल की प्रतीक्षा कर रहा है लेकिन किसी भी कारण से - यह वास्तव में किसी भी प्रकार के लूप में नहीं है या संसाधन की प्रतीक्षा नहीं कर रहा है। दूसरा, अगर आप बंद संकेत प्राप्त करने के बाद कुछ (शायद छोड़े गए) कार्यकर्ता में सफाई कोड निष्पादित करने की जरूरत थी, तो अपनी सेवा नहीं कार्यकर्ता धागा को साफ करने के लिए पर्याप्त समय दे सकता है।

लेकिन, मूल रूप से, आपने जो कुछ किया है, वह समस्या को एक अलग धागे में ले जाया गया है। यह सेवा सेवा नियंत्रक के लिए उत्तरदायी नहीं रख सकता है लेकिन यह डिजाइन समस्या हल नहीं होती है - और यह धागे और mutexes का उपयोग करके अनावश्यक जटिलता का एक बहुत कहते हैं, आखिरकार यह आपकी सेवा को डीबग करने के लिए कठिन होगा यदि आपको कभी भी आवश्यकता हो।

मान लीजिए कि आप कुछ कोड हर 5 सेकंड पर अमल करने की जरूरत है करते हैं। विचार है कि, 5 सेकंड "प्रतीक्षा" करने के बजाय, आप नियंत्रण को उलटा करते हैं, और टाइमर को आपके काम का आह्वान करने दें।

यह बुरा है:

protected override void OnStart(string[] args) 
{ 
    while (true) 
    { 
     RunScheduledTasks(); // This is your "work" 
     Thread.Sleep(5000); 
    } 
} 

यह अच्छा है:

public class MyService : ServiceBase 
{ 
    private Timer workTimer; // System.Threading.Timer 

    protected override void OnStart(string[] args) 
    { 
     workTimer = new Timer(new TimerCallback(DoWork), null, 5000, 5000); 
     base.OnStart(args); 
    } 

    protected override void OnStop() 
    { 
     workTimer.Dispose(); 
     base.OnStop(); 
    } 

    private void DoWork(object state) 
    { 
     RunScheduledTasks(); // Do some work 
    } 
} 

यह है कि। नियमित अंतराल पर काम करने के लिए आपको बस इतना करना है। जब तक कार्य एक समय में सेकंड के लिए नहीं चलता है, तब तक आपकी सेवा सेवा नियंत्रक के प्रति उत्तरदायी रहेगी। तुम भी इस परिदृश्य के तहत रोक का समर्थन कर सकते हैं:

protected override void OnPause() 
{ 
    workTimer.Change(Timeout.Infinite, Timeout.Infinite); 
    base.OnPause(); 
} 

protected override void OnContinue() 
{ 
    workTimer.Change(0, 5000); 
    base.OnContinue(); 
} 

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

आपकी सेवा में बहुप्रचारित अर्थशास्त्र शुरू करना शुरू करना सबसे अच्छा नहीं है जब तक कि आपको वास्तव में इसकी आवश्यकता न हो। यदि आप काम की छोटी-छोटी इकाइयों को निर्धारित करने की कोशिश कर रहे हैं, तो आपको निश्चित रूप से इसकी आवश्यकता नहीं है।

+0

किसी कारण से मैं इस धारणा के तहत था कि यदि मेरे पास कोई थ्रेड नहीं चल रहा था तो सेवा समाप्त हो जाएगी। –

+0

@Spencer Ruport: 'ऑनस्टार्ट' विधि समाप्त होने पर अभी भी एक थ्रेड चल रहा है, वैसे ही एक थ्रेड चल रहा है जब WinLorms 'Form' में 'ऑनलोड' समाप्त होता है। अपना 'ऑनस्टार्ट' कोड चलाने के बाद, सेवा एक संदेश लूप में जाती है जहां यह सेवा नियंत्रक से संकेतों की प्रतीक्षा करता है। – Aaronaught

+0

क्या होगा यदि RunScheduledTasks() चलाने के लिए एक अप्रत्याशित और संभावित रूप से लंबा समय लगता है? उपर्युक्त उदाहरण के संदर्भ में, मान लीजिए कि इसे चलाने में 15 सेकंड तक लग सकते हैं। उस मामले में टाइमर दृष्टिकोण अब काम नहीं करेगा, है ना? मेरा मतलब है कि विचार प्रत्येक रन के बीच RunScheduledTasks() में 5 सेकंड होगा। उस मामले में थ्रेड। स्लीप दृष्टिकोण नौकरी के लिए सबसे उपयुक्त लगता है, जब तक कि मुझे कुछ याद नहीं आ रहा है? –

1

मैंने हाल ही में एक सेवा लिखी है जिसे कुछ काम करना था, फिर एन मिनट, फिर लूप का इंतजार करें।

मैंने मैनुअल रीसेट (जिसे _evt कहा जाता है) और ऑनस्टॉप में सेट() को कॉल करने के लिए भी इस्तेमाल किया। लेकिन मुझे टाइमर की आवश्यकता नहीं थी।

सेवा धागा में, मैं था:

for (;;) { 

    // do some work 
    if (_evt.WaitOne(_waitInterval)) { 

     // got the signal => time to leave 
     break; 
    } 
} 

तो, या तो एक समय समाप्त हुआ => कुछ और काम करने के लिए समय है। या सेट() कहा जाता है और लूप समाप्त हो जाता है।

+0

दिलचस्प। काम कितना समय ले रहा था? क्या ऐसे समय होंगे जब विंडोज़ में स्टॉप मारना होगा जबकि कोड 'WaitOne (n)' पर वापस आ रहा है? –

+0

काम में कुछ सेकंड लग सकते हैं। ऑनस्टॉप में पहली चीज एससीएम को बताने के लिए कृपया 10 सेकंड प्रतीक्षा करें। – Timores

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

  • कोई संबंधित समस्या नहीं^_^